前言
本文章实现一个触底无限加载的功能,简言之就是当还有数据未加载完毕时,显示正在加载中,全部加载完毕后显示加载已完毕的一个效果。一起来看看如何实现~
一、封装的意义
- 数据较多的时候,滑动滚动条显示加载状态,可以给用户很好的体验
- 代码维护性更好
- 代码可复用
二、如何封装?
需要用到@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