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

Pitfalls and solutions encountered in MySQL timestamp comparison query

Table of contents Pitfalls encountered in timesta...

Detailed explanation of MySQL date string timestamp conversion

The conversion between time, string and timestamp...

Let's talk about my understanding and application of React Context

Table of contents Preface First look at React Con...

In-depth analysis of the slow query problem of MySQL Sending data

Through an example, I shared with you the solutio...

JavaScript jigsaw puzzle game

This article example shares the specific code of ...

A brief discussion on docker compose writing rules

This article does not introduce anything related ...

Navigation Design and Information Architecture

<br />Most of the time when we talk about na...

Detailed steps for creating a Vue scaffolding project

vue scaffolding -> vue.cli Quickly create a la...

Markup Language - Print Style Sheets

Click here to return to the 123WORDPRESS.COM HTML ...

Solution to MySQL root password error number 1045

Stop MySQL Service Windows can right-click My Com...

MySQL query learning basic query operations

Preface MySQL is the most popular relational data...

The functions and differences between disabled and readonly

1: readonly is to lock this control so that it can...

HTML imitates Baidu Encyclopedia navigation drop-down menu function

HTML imitates the Baidu Encyclopedia navigation d...

Talking about the practical application of html mailto (email)

As we all know, mailto is a very practical HTML ta...