vue3——自己实现数据无限加载功能的封装

828 阅读1分钟

前言

本文章实现一个触底无限加载的功能,简言之就是当还有数据未加载完毕时,显示正在加载中,全部加载完毕后显示加载已完毕的一个效果。一起来看看如何实现~


一、封装的意义

  • 数据较多的时候,滑动滚动条显示加载状态,可以给用户很好的体验
  • 代码维护性更好
  • 代码可复用

二、如何封装?

需要用到@vueuse/core中的useIntersectionObserver,用来判断元素是否出现在可视区 链接:useIntersectionObserver

1. 准备

项目根目录下打开任意终端,执行npm install @vueuse/core@5.3.0,这里安装的固定版本,各位按需选择

因考虑复用组件,故封装为全局组件,老套路src/components下新建infinite-loading.vue文件

代码如下(示例):

<template>
  <div class="infinite-loading" ref="container">
    <div class="loading" v-if="loading">
      <span class="img"></span>
      <span class="text">正在加载中...</span>
    </div>
    <div class="none" v-if="finished">
      <span class="img"></span>
      <span class="text">亲,没有更多了</span>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
  name: 'InfiniteLoading',
  props: {
    loading: {
      type: Boolean,
      default: false
    },
    finished: {
      type: Boolean,
      default: false
    }
  },
  setup (props, { emit }) {
    const container = ref(null)
    useIntersectionObserver(
      container,
      ([{ isIntersecting }], dom) => {
        if (isIntersecting) {
          // 当loading和finished的值都为false时,就通知父组件调用方法继续向后台请求数据
          if (props.loading === false && props.finished === false) {
            emit('infinite')
          }
        }
      },
      {
        threshold: 0
      }
    )
    return { container }
  }
}
</script>

<style scoped lang='less'>
.infinite-loading {
  .loading {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 200px;
    .img {
      width: 200px;
      height: 200px;
      background: url(https://code-1307161657.cos.ap-beijing.myqcloud.com/images%2Fload.gif) no-repeat center / contain;
    }
    .text {
      color: #999;
      font-size: 16px;
    }
  }
  .none {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 200px;
    .img {
      width: 200px;
      height: 134px;
      background: url(https://code-1307161657.cos.ap-beijing.myqcloud.com/images%2Fnone.png) no-repeat center / contain;
    }
    .text {
      color: #999;
      font-size: 16px;
    }
  }
}
</style>

可以直接在要使用的组件中,注册一下。也可看之前文章,使用vue插件的方式注册为全局组件,这里就不演示了~

2. 使用

在任意.vue结尾文件中使用

代码如下(示例): 代码中注释为书写思路,改为接口方法向后台发送请求即可

<template>
 <div class="home-container">
   <InfiniteLoading :loading="loading" :finished="finished" @infinite="getData"/>
 </div>
</template>

<script>
import { ref } from 'vue'
export default {
  name: 'App',
  setup () {
    const loading = ref(true)
    const finished = ref(true)

    const getData = () => {
      // 开始向后台请求数据,loading的值设置为true
      // 表示开始请求数据,显示加载中的样式
      // loading.value = true

      // 当本次调用结束后,将loading的值设置为false,表示本次结束
      // loading.value = false
      // 将页码++

      // 当所有数据加载完毕,将finished的值设置为true
      // finished.value = true
      // 表示所有数据加载完毕,显示加载已完毕的样式
    }

    return { loading, finished, getData }
  }

}
</script>

<style lang="less">
.home-container {
  margin: 100px auto;
  width: 1000px;
  height: 500px;
}
</style>

三、 效果演示

加载中效果 在这里插入图片描述

加载完毕效果 在这里插入图片描述


总结

Always believe that efforts will be rewarded