Vue实现无限加载瀑布流

 更新时间:2021年11月04日 11:50:20   作者:immocha  
这篇文章主要为大家详细介绍了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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • vue-router动态设置页面title的实例讲解

    vue-router动态设置页面title的实例讲解

    今天小编就为大家分享一篇vue-router动态设置页面title的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Vue.js组件使用props传递数据的方法

    Vue.js组件使用props传递数据的方法

    这篇文章主要为大家详细介绍了Vue.js组件使用props传递数据的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • vue 实现cli3.0中使用proxy进行代理转发

    vue 实现cli3.0中使用proxy进行代理转发

    今天小编就为大家分享一篇vue 实现cli3.0中使用proxy进行代理转发,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • vue动态代理无须重启项目解决方案详解

    vue动态代理无须重启项目解决方案详解

    这篇文章主要为大家介绍了vue动态代理无须重启项目解决方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Vue router配置与使用分析讲解

    Vue router配置与使用分析讲解

    第一次写Vue项目,要用到router.js,看了一下官方文档,还是很懵逼,不知道怎么配置,又去看视频查资料,最后终于搞定了。话不多说,先上代码,我再讲一些要注意的细节
    2022-12-12
  • vue在项目中实现base64加密解密的示例代码

    vue在项目中实现base64加密解密的示例代码

    这篇文章主要为大家详细介绍了vue在项目中实现base64加密解密的两种方法,文中的示例代码讲解详细,具有一定的参考价值,有需要的小伙伴可以了解一下
    2023-10-10
  • vue中el-table实现穿梭框(数据可以上移下移)

    vue中el-table实现穿梭框(数据可以上移下移)

    本文主要介绍了vue中el-table实现穿梭框(数据可以上移下移),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • vue如何跳转到其他页面

    vue如何跳转到其他页面

    跳转到指定URL,向history栈添加一个新的纪录,点击后退会返回至上一个页面,这篇文章给大家介绍vue如何跳转到其他页面,包括无参跳转和带参跳转,本文结合实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2023-10-10
  • vue3 Table分页保留选中状态代码示例

    vue3 Table分页保留选中状态代码示例

    这篇文章主要给大家介绍了关于vue3 Table分页保留选中状态的相关资料,vue table组件是一个非常方便的表格组件,它可以帮助我们实现分页和选中功能,需要的朋友可以参考下
    2023-08-08
  • Vue局部组件数据共享Vue.observable()的使用

    Vue局部组件数据共享Vue.observable()的使用

    随着组件的细化,就会遇到多组件状态共享的情况,今天我们介绍的是 vue.js 2.6 新增加的 Observable API ,通过使用这个 api 我们可以应对一些简单的跨组件数据状态共享的情况,感兴趣的可以了解一下
    2021-06-06

最新评论