网络编程
位置:首页>> 网络编程>> JavaScript>> Vue实现无限加载瀑布流

Vue实现无限加载瀑布流

作者:immocha  发布时间:2024-05-09 15:23:16 

标签:vue,加载,瀑布流

本文实例为大家分享了Vue实现无限加载瀑布流的具体代码,供大家参考,具体内容如下

Vue实现无限加载瀑布流

我做的这个瀑布流放在了一个嵌套页面里,就是类似管理后台的main content中,如果要改成全屏的也很方便,其实更容易些,因为会避开一些在元素上使用onScroll的坑。

通过这个瀑布流,可以掌握以下几个知识点:

1、在元素上监听scroll事件,相对直接在window上监听麻烦一点点;
2、image.onload事件;
3、promiseAll;
4、vue 的 transition-group

这里使用了mockjs来模拟图片数据,然后通过axios来调用图片数据,也可使用其他数据源。

通过计算图片高度,判断把图片加载到哪一列。
如果屏幕还有空余,那就继续加载。
无限滚动加载。
屏幕resize这块没有做,后期可以加上去。

直接贴代码,有问题欢迎切磋。


<template>
 <div class="waterfall wf-wrap" ref="waterfall" @scroll="onScroll">
   <ul>
     <transition-group name="list" tag="li">
       <li
         v-for="(item,index) in waterfallList"
         :key="index"
         class="wf-item"
         :style="{top:item.top+ 'px',left:item.left+'px', width:item.width+'px', height:item.height + 'px'}"
       >
         <img :src="item.src" />
       </li>
     </transition-group>
   </ul>
 </div>
</template>
<script>
import { getList } from "@/api/demo";

export default {
 name: "Waterfall",
 data() {
   return {
     waterfallList: [],

waterfallCol: 5,
     colWidth: 236,
     marginRight: 10,
     marginBottom: 10,
     colHeights: [],

listQuery: {
       page: 1,
       limit: 5,
       sort: "+id"
     },
     loading: false,
     show: true
   };
 },
 mounted() {
   this.init();
 },
 methods: {
   init() {
     // 初始化时,每栏高度都为0
     this.colHeights = new Array(this.waterfallCol);
     for (let i = 0; i < this.colHeights.length; i++) {
       this.colHeights[i] = 0;
     }
     this.colWidth =
       (this.$refs.waterfall.clientWidth -
         (this.waterfallCol - 1) * this.marginRight) /
       this.waterfallCol;
     this.loadImgs();
   },

loadImgs() {
     this.loading = true;
     // 从api获取数据
     getList(this.listQuery).then(res => {
       let images = res.data.items;
       let promiseAll = [],
         imgs = [],
         total = images.length;

for (let i = 0; i < total; i++) {
         promiseAll[i] = new Promise(resolve => {
           imgs[i] = new Image();
           imgs[i].src = images[i].image_uri;
           imgs[i].onload = () => {
             let imgData = {};
             imgData.height = (imgs[i].height * this.colWidth) / imgs[i].width;
             imgData.width = this.colWidth;
             imgData.src = images[i].image_uri;
             this.waterfallList.push(imgData);
             this.rankImgs(imgData);
             resolve(imgs[i]);
           };
         });
       }
       Promise.all(promiseAll).then(() => {
         this.loading = false;
         this.loadMore();
       });
     });
   },

loadMore() {
     if (
       this.$refs.waterfall.clientHeight + this.$refs.waterfall.scrollTop >
         this.filterMin().minHeight &&
       this.loading == false
     ) {
       this.loading = true;
       setTimeout(() => {
         this.loadImgs();
       }, 200);
     }
   },

rankImgs(imgData) {
     let min = this.filterMin();
     imgData.top = min.minHeight;
     imgData.left = min.minIndex * (this.colWidth + this.marginRight);

this.colHeights[min.minIndex] += imgData.height + this.marginBottom;
   },

filterMin() {
     let minHeight = Math.min.apply(null, this.colHeights);
     return {
       minHeight: minHeight,
       minIndex: this.colHeights.indexOf(minHeight)
     };
   },

onScroll() {
     this.loadMore();
   }
 }
};
</script>

<style lang="scss" scoped>
ul li {
 list-style: none;
}

.wf-wrap {
 position: relative;
 width: 100%;
 height: 100%;
 overflow: scroll;
}
.wf-item {
 position: absolute;
}
.wf-item img {
 width: 100%;
 height: 100%;
}
.list-enter-active,
.list-leave-active {
 transition: all 1s;
}
.list-enter, .list-leave-to
/* .list-leave-active for below version 2.1.8 */ {
 opacity: 0;
 transform: translateY(30px);
}
</style>

来源:https://blog.csdn.net/immocha/article/details/107159815

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com