The effect

The overall analysis

A standalone global component that, if visible, tells the next page to load data, and if successfully loaded, is pushed to the bottom of the invisible until there is no more data to load

Code implementation

Component packaging

The structure and style of the component

<template>
  <div class="infinite-loading" ref="container">
    <! -- display while loading data -->
    <div class="loading" v-if="isLoading">
      <span class="img"></span>
      <span class="text">Loading...</span>
    </div>
    <! -- Display data when all loaded -->
    <div class="finished" v-if="isFinished">
      <span class="text">Honey, there is no more</span>
    </div>
  </div>
</template>

<script>
export default {
  name: 'InfiniteLoading'.props: {
    // Whether it is loading
    isLoading: {
      type: Boolean.default: false
    },
    // All data is loaded
    isFinished: {
      type: Boolean.default: false}}}</script>

<style scoped lang='less'>
.infinite-loading {
  .loading {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 200px;
    .img {
      width: 50px;
      height: 50px;
      background: url('~@/assets/images/load.gif') no-repeat center / contain;
    }
    .text {
      color: # 999;
      font-size: 16px; }}.finished {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 200px;
    .text {
      color: # 999;
      font-size: 16px; }}}</style>
Copy the code

The component is registered globally after encapsulation and then tested on an empty page

/ / register.import InfiniteLoading from './infinite-loading'

export default {
  install (app) {
    ...
    app.component(InfiniteLoading.name, InfiniteLoading)
  }
}
Copy the code

Renderings, pictures need to be changed



Function implementation

<script>
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
  name: 'InfiniteLoading'.emits: ['load'].props: {
    isLoading: {
      type: Boolean.default: false
    },
    isFinished: {
      type: Boolean.default: false}},// Data lazy loading. If the component enters the viewable area, the parent component is told to load new data
+ setup (props, { emit }) {
+   const target = ref(null)
+   useIntersectionObserver(
+     target,
+     ([{ isIntersecting }], dom) = >{+if (isIntersecting) {
+         if (props.isLoading === false && props.isFinished === false) {+// The load event is triggered only when the data is not being loaded and not completely finished
+           emit('load')
+         }
+       }
+     }, {
+       threshold: 0+} +) +return { target }
+ }
}
</script>
Copy the code

Component Usage (Example)

rendering

implementation

setup(){...const isFinished = ref(false) // Check whether the load is complete
  const isLoading = ref(false)
  const loadData = () = > {
    isLoading.value = true
    findSubCategoryGoods(reqParams).then(res= > {
      // reqParams is the request parameter
      isLoading.value = false 			
      if (res.result.items.length) {
        isFinished.value = false
        reqParams.page++
      } else {
        isFinished.value = true} goodList.value.push(... res.result.items) }) }return {isFinished,isLoading,loadData}
}  
Copy the code