我是靠谱客的博主 甜美小甜瓜,最近开发中收集的这篇文章主要介绍组件封装 - 无限加载数据组件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

首先我们得了解无限加载数据组件是一个什么东西?

它就是一个盒子, 简单来说就是一个 div ; 这一个盒子里面有两个子元素

1. loading 的效果

2. 父组件数据加载完毕之后的效果, 我取名为 finished

组件内部需要接收父组件传过来的 loading 和 finished 值, 在模板中使用 v-if 进行动态的判断; 到底需要显示哪一个效果

我们还需要了解一个问题就是, 什么时候什么条件的加持下; 该去发送数据, 在模板中渲染?

这个问题也跟此组件有关, 我们可以监听这个组件(也就是监听这个 div); 如果这个 div 出现在了可视区, 我们就通知父组件调用数据, 渲染数据即可

最后一个问题就是, 如何实现数据的无限加载?

实现的思想主要是使用的分页加载, 当前页面数据已经返回; 就到动态的将 page++ , 再次获取的数据和原先的数据进行合并; 这样的往复动作就可以实现数据无线加载

思路分析:

1. 父组件内部需要提供 loading 和 finished 数据, 传给子组件(无限加载组件)

2. 子组件内部通过 v-if 判断, 最终显示哪一个效果

3. 子组件内部还需提供监听模板元素的方法, 当监听对象进入可视区; 就通知父组件调用接口

4. 父组件需要接收子组件抛出的信息, 内部封装调用接口的函数; 收到消息就直接调用

5. 父组件中定义一个响应式的数组, 每一次后端的数据返回就动态的 push 进去; 且修改 page 值

<template>
  <div class="xtx-infinite-loading" ref="target">
    <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: 'XtxInfiniteLoading',
  props: {
    loading: {
      type: Boolean,
      default: false
    },
    finished: {
      type: Boolean,
      default: false
    }
  },
  setup (props, { emit }) {
    const target = ref(null)

    // 监听元素是否已经在可视区内
    useIntersectionObserver(
      target,
      ([{ isIntersecting }], dom) => {
        if (isIntersecting) {
          if (props.loading === false && props.finished === false) {
            // 如果两个状态都为false, 说明数据还可以继续加载且前一次数据已经响应完毕
            emit('infinite')
          }
        }
      },
      {
        threshold: 0
      }
    )
    return { target }
  }
}
</script>

<style scoped lang='less'>
.xtx-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;
    }
  }
  .none {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 200px;
    .img {
      width: 200px;
      height: 134px;
      background: url(../../assets/images/none.png) no-repeat center / contain;
    }
    .text {
      color: #999;
      font-size: 16px;
    }
  }
}
</style>
<template>
  <div class="sub-category">
    <div class="container">
      <!-- 二级类目面包屑 -->
      <SubBread />

      <!-- 筛选区 -->
      <SubFilter />

      <div class="goods-list">
        <!-- 排序 -->
        <SubSort />
        <!-- 列表 -->
        <ul>
          <li v-for="item in goodsList" :key="item.id" >
            <GoodsItem :goods="item" />
          </li>
        </ul>

        <!-- 无限加载组件 -->
        <!-- 此组件需要放在列表组件后面, 组件初始化的时候; 商品列表是空的, 所以此组件一开始就会在可视区里面 -->
        <XtxInfiniteLoading :loading="loading" :finished="finished" @infinite="getData" />
      </div>
    </div>
  </div>

</template>

<script>
import SubBread from './components/sub-bread.vue'
import SubFilter from './components/sub-filter'
import SubSort from './components/sub-sort'
import GoodsItem from './components/goods-item'
import { findSubCategoryGoods } from '@/api/category'
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
export default {
  name: 'SubCategory',
  components: { SubBread, SubFilter, SubSort, GoodsItem },
  setup () {
    // 控制无限加载组件的数据
    const loading = ref(false)
    const finished = ref(false)

    const route = useRoute()

    // 分页显示数据
    let reqParams = {
      page: 1,
      pagsize: 20,
      categoryId: route.params.id
    }

    // 后端返回的数据集合
    const goodsList = ref([])

    // 获取商品数据函数
    const getData = () => {
      loading.value = true
      findSubCategoryGoods(reqParams).then(({ result }) => {
        // 数据还有
        if (result.items.length) {
          goodsList.value.push(...result.items)
          reqParams.page++
        } else {
          // 数据已经加载完毕
          finished.value = true
        }
        loading.value = false
      })
    }

    // 二级类目路由id发生变化立即进行
    watch(() => route.params.id, (newVal) => {
      if (newVal && route.path === `category/sub/${newVal}`) {
        // 清空原先商品id所获取的数据
        goodsList.value = []

        // 初始化后端需求数据
        reqParams = {
          page: 1,
          pagsize: 20,
          categoryId: newVal
        }

        // 将finished效果隐藏
        finished.value = true
      }
    }, { immediate: true })

    return { loading, finished, goodsList, getData }
  }
}
</script>

<style scoped lang="less">
.goods-list {
  background: #fff;
  padding: 0 25px;
  margin-top: 25px;
  ul {
    display: flex;
    flex-wrap: wrap;
    padding: 0 5px;
    li {
      margin-right: 20px;
      margin-bottom: 20px;
      &:nth-child(5n) {
        margin-right: 0;
      }
    }
  }
}
</style>

最后

以上就是甜美小甜瓜为你收集整理的组件封装 - 无限加载数据组件的全部内容,希望文章能够帮你解决组件封装 - 无限加载数据组件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部