@Wangww0925
2019-08-07T05:47:05.000000Z
字数 4936
阅读 268
vue-cli
瀑布流结合了 onresize事件、onscroll事件。onresize事件主要是为了监听窗口尺寸变化;onscroll事件主要是为了滚动到底部加载更多数据
$ul 是li的外部ul,可修改spacingW 间距,可修改columnNum 列数,可修改,默认2vue文件
<template><div><ul class="article_list w" ref="article_list"><li class="item" v-for="(item,i) in imgsArr"><router-link :to="{path:'Detail', query: {id: item.id} }"><img class="w" :src="item.path" alt=""><p class="ti24" v-text="item.summary"></p></router-link></li></ul><div v-if="!isMore"><p class="tc" v-text="isMoreText"></p></div><div class="loading tc" v-if="isFirstLoad" style="font-size: 30px;">正在加载中...</div></div></template><script>import store from '@/store/store';export default {store,data () {return {ajaxData:{ // 列表请求数据page: 0, // 当前加载的加载图片的次数},imgsArr: [], // 列表数据isFirstLoad:true, // loadingisMore:true, // true-还有更多isMoreText:'没有更多的内容了',isPreloading:true, // 滚动到底部,并且能获取数据}},methods: {DateRenew(){ // 列表初始化this.imgsArr = []; // 列表数据this.ajaxData.page = 0; // 页码this.removeScroll();this.scroll();this.getData();},getData() { // 请求列表console.log(this.ajaxData)this.isFirstLoad = true; // loading显示this.$http.get("http://118.24.194.224:20001/api/blog/article-list").then((res)=>{this.ajaxData.page++let result = res.data.body.dataconsole.log(res)this.ajaxData.page == 0 ? this.imgsArr = [] : ""; // 避免多次请求出现数据重复this.imgsArr = this.imgsArr.concat(result)this.getPosition()this.isFirstLoad = false; // loading隐藏},(res)=>{console.log(res)})},getPosition() { // 不固定列宽的瀑布流let that = this;let $ul = that.$refs.article_list;let spacingW = 15; // 间距var columnNum = 2; // 一列个数// 延迟是为了解决ul下的li获取不到问题setTimeout(function (){let ulW = $ul.offsetWidth;let listArr = []; // 存放每个li的top + height值let $list = $ul.children;ulW > 900 ? columnNum = 3 : ""; // 大于宽度900的列数为 3// 如果宽度相等,不执行定位if(ulW < 700){$ul.style.height = "auto"for(var j = 0; j < $list.length; j++){$list[j].style.position = "";$list[j].style.width = "100%";$list[j].style.marginBottom = "15px";$list[j].setAttribute("class","item fadeOut");}}// 瀑布流布局逻辑if(ulW >= 700){for(var i = 0; i < $list.length; i++){$list[i].style.position = "absolute";$list[i].style.marginBottom = "0px";// 设置列宽let liW = (ulW - spacingW * (columnNum - 1)) / columnNum; // 每个宽度 = (总宽 - 间距)/ 一列个数$list[i].style.width = `${ liW }px`;// 当前列高let liH = $list[i].offsetHeight;// 设置 top 值;小于一行的个数top都为0if(i < columnNum){$list[i].style.top = 0;$list[i].style.left = `${ (liW + spacingW) * i }px`;listArr[i] = liH;}else{let minTopHeight = Math.min.apply(null, listArr); // 获取数组中的最小值let minIndex = listArr.indexOf(minTopHeight); // 获取数组中最小值的索引let liTopHeight = minTopHeight + spacingW; // 当前 top = 上一行对应列的top + 上一行对应列的height + 间距$list[i].style.top = `${ liTopHeight }px`;$list[i].style.left = `${ $list[minIndex].offsetLeft }px`; // left = 最低高的leftlistArr[minIndex] = $list.length * 500; // 确保下一次获取最小值时不会再次获取到;$list.length * 500 让其一定比数组中所有的值大listArr[i] = liTopHeight + liH; // 将当前top + 当前height 放到数组中}$list[i].setAttribute("class","item fadeOut");}let lastEle = $list[$list.length - 1]; // 获取最后一个li$ul.style.height = `${lastEle.offsetTop + lastEle.offsetHeight + 50 }px`; // 设置ul高度 = 最后一个li的top + 最后一个li的height + 50}// 判断无更多数据// 由于setTimeout是异步,所以isMore不能在返回数据时就判断,会照成没有更多内容提早显示,给用户造成体验不好的感觉if (that.ajaxData.page === 3) { // 模拟已经无新数据that.removeScroll()that.isMore = false;that.isPreloading = false;}else{that.isMore = true;that.isPreloading = true; // 滚动到底部还原,让其可以继续加载数据}},500)},scroll(){ // 绑定滚动事件window.addEventListener('scroll', this.scrollFun,true)},scrollFun(){ // 处理滚动事件let $ul = this.$refs.article_list;let innerHeight = $ul.clientHeight; // 可滚动容器的高度let outerHeight = document.documentElement.clientHeight; // 屏幕尺寸高度letlet scrollTop = document.documentElement.scrollTop; // 可滚动容器超出当前窗口显示范围的高度// 判断滚动到底部if (innerHeight < (outerHeight + scrollTop)) {if (this.isPreloading && !this.isMore){ // 可以加载数据,并且数据没有全部加载完毕this.isPreloading = false // 滚动到底部不能加载数据,等待数据处理完毕时才可以加载数据this.getData() // 加载数据}}},removeScroll(){ // 解除滚动事件window.removeEventListener('scroll', this.scrollFun)}},created : function (){// console.log("2 - created 实例对象创建完成")this.DateRenew()},watch:{ // 监听'$store.state.windowResizeW':function(){ // 监听屏幕宽度变化this.getPosition()},'$store.state.windowResizeH':function(){ // 监听屏幕高度变化this.getPosition()}}}</script><style scoped lang="stylus">.wwidth:100%;.ti34text-indent:24px;.tctext-align: center;.boxShadowbox-shadow:0 2px 2px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.06), 0 1px 5px 0 rgba(0,0,0,0.12), 0 -1px 0.5px 0 rgba(0,0,0,0.09);vendor(prop, n)-webkit-{prop}:n;-moz-{prop}:n;-ms-{prop}:n;-o-{prop}:n;{prop}:n;.itemwidth:100%;background-color:#fff;padding:10px;opacity:0;vendor('transition',opacity 2s)&:hovervendor('transform', translateY(-1px));box-shadow: 0 1px 3px rgba(0,0,0,.02), 0 9px 15px -4px rgba(0,0,0,.17);.fadeOutopacity:1;.loadingheight:50px;line-height:50px;text-align:center;@media screen and (min-width: 992px).article_listposition:relative;.item@extend .boxShadow;</style>
作者 wendy
2019 年 1月 4日