Vue implements infinite loading waterfall flow

Vue implements infinite loading waterfall flow

This article example shares the specific code of Vue to achieve infinite loading waterfall flow for your reference. The specific content is as follows

The waterfall flow I made is placed in a nested page, which is similar to the main content of the management background. If you want to change it to full screen, it is also very convenient. In fact, it is easier because it avoids some pitfalls of using onScroll on elements.

Through this waterfall flow, you can master the following knowledge points:

1. Listening to scroll events on elements is a little more troublesome than listening directly on window;
2. image.onload event;
3. promiseAll;
4. Vue's transition-group

Here, mockjs is used to simulate the image data, and then the image data is called through axios. Other data sources can also be used.

By calculating the image height, determine which column to load the image into.
If there is still room on the screen, continue loading.
Infinite scroll loading.
Screen resizing has not been done, but it can be added later.

Paste the code directly, if you have any questions, please feel free to discuss.

<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() {
      // When initialized, the height of each column is 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;
      // Get data from the 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>

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • Vue implements waterfall flow component sliding to load more
  • Vue waterfall flow component realizes pull-up loading more
  • Vue implements simple waterfall flow layout
  • Vue implements network picture waterfall flow + pull down to refresh + pull up to load more (detailed steps)
  • Write a waterfall plug-in code example through vue
  • Example of using Vue waterfall plugin
  • vue.js component vue-waterfall-easy realizes waterfall flow effect

<<:  Non-standard implementation code for MySQL UPDATE statement

>>:  Detailed explanation of four solutions for implementing in-line scrolling on mobile devices

Recommend

Perform data statistics on different values ​​of the same field in SQL

Application scenario: It is necessary to count th...

Details of 7 kinds of component communication in Vue3

Table of contents 1. Vue3 component communication...

How to use SVG icons in WeChat applets

SVG has been widely used in recent years due to i...

js to achieve a simple carousel effect

This article shares the specific code of js to ac...

Html Select uses the selected attribute to set the default selection

Adding the attribute selected = "selected&quo...

Vue implements simple data two-way binding

This article example shares the specific code of ...

How to view the IP address of the Docker container

I always thought that Docker had no IP address. I...

Optimizing query speed of MySQL with tens of millions of data using indexes

1. The role of index Generally speaking, an index...

JavaScript counts the number of times a character appears

This article example shares the specific code of ...