效果
整体分析
一个独立的全局组件,如果这个组件可见,通知下一页加载数据,如果加载成功又会被挤到最下边不可见,直到没有数据可以加载,就显示没有更多数据
代码实现
组件封装
组件的结构和样式
<template>
<div class="infinite-loading" ref="container">
<!-- 正在加载数据时显示 -->
<div class="loading" v-if="isLoading">
<span class="img"></span>
<span class="text">正在加载...</span>
</div>
<!-- 数据全部加载完毕时显示 -->
<div class="finished" v-if="isFinished">
<span class="text">亲,没有更多了</span>
</div>
</div>
</template>
<script>
export default {
name: 'InfiniteLoading',
props: {
// 是否在加载中
isLoading: {
type: Boolean,
default: false
},
// 数据全部加载完毕
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>
组件封装完成后在全局注册然后在一个空页面测试
// 注册
...
import InfiniteLoading from './infinite-loading'
export default {
install (app) {
...
app.component(InfiniteLoading.name, InfiniteLoading)
}
}
效果图,图片需要换
功能实现
<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
}
},
// 数据懒加载,如果这个组件进入可视区域就通知父组件加载新的数据
+ setup (props, { emit }) {
+ const target = ref(null)
+ useIntersectionObserver(
+ target,
+ ([{ isIntersecting }], dom) => {
+ if (isIntersecting) {
+ if (props.isLoading === false && props.isFinished === false) {
+ // 只有数据不在加载中且还没全部结束时才触发load事件
+ emit('load')
+ }
+ }
+ }, {
+ threshold: 0
+ }
+ )
+ return { target }
+ }
}
</script>
组件使用(举例)
效果图
实现
setup(){
...
const isFinished = ref(false) // 是否全部加载完毕
const isLoading = ref(false)
const loadData = () => {
isLoading.value = true
findSubCategoryGoods(reqParams).then(res => {
// reqParams为请求的参数
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}
}