1、创建加载更多组件的结构、样式
<template> <div class="xtx-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>
<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>
loading 默认是 false 是否触底加载
finished 默认是 false 是否全部加载完成
2、监听组件是否进入可视区,给父组件派发事件
<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 container = ref(null) // 触底组件是否进入可视区 useIntersectionObserver( container, ([{ isIntersecting }], dom) => { if (isIntersecting) { if (props.loading === false && props.finished === false) { //给父组件派发事件,父组件内调用接口API请求数据,渲染页面 emit('infinite') } } }, { threshold: 0 } ) return { container } } } </script>
3、父组件内,接受并定义事件
4、当触发事件时
loading的值为true
调用接口API
数据返回值赋值合并 list 数组
loading的为false
页码++
判断 list.value.length===res.result.counts 时,将 finished 的值改为true,表示完成全部数据的加载,没有更多数据了
5、监听页面路由的变化,当切商品分类时 ( 根据需要,判断路由路径 route.fullPath ),
将 list.value置为空
将loading的值为false
将finished的值为false
将页码的值为1
<template> <!-- 加载更多 --> <XtxInfiniteLoading :loading="loading" :finished="finished" @infinite="getData" /> </template>
<script> import { ref, reactive, watch } from 'vue' import { useRoute } from 'vue-router' //接口API方法 import { findSubCategoryGoods } from '@/api/category.js' export default { name: 'SubCategory', setup () { const route = useRoute() // 单次接口调用的状态 const loading = ref(false) // 加载完成的标志 const finished = ref(false) // 商品总数 const total = ref(0) // 商品列表 const list = ref([]) // 请求参数 const reqParams = reactive({ page: 1, pageSize: 10 }) const getData = () => { // 设置接口正在调用 loading.value = true findSubCategoryGoods(reqParams).then(ret => { // 把本次加载的数据追加到列表中 list.value.push(...ret.result.items) // 获取商品列表的总数 total.value = ret.result.counts // 本次接口调用完成 loading.value = false if (list.value.length === total.value && total.value !== 0) { // 没有更多数据了 finished.value = true } // 页码需要累加 reqParams.page += 1 }) } // 如果二级分类发生变化,重置当前的数据 watch(() => route.params.id, (newVal) => { // 判断是否为二级分类 if (route.fullPath !== '/category/sub/' + newVal) return // 重置数据 list.value = [] total.value = 0 loading.value = false finished.value = false reqParams.page = 1 }) return { loading, finished, getData, list } } } </script>
08-24