欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue实现无限加载瀑布流

程序员文章站 2022-03-12 22:27:27
本文实例为大家分享了vue实现无限加载瀑布流的具体代码,供大家参考,具体内容如下我做的这个瀑布流放在了一个嵌套页面里,就是类似管理后台的main content中,如果要改成全屏的也很方便,其实更容易...

本文实例为大家分享了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>

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