👻:我们在日常开发当中"滚动加载数据"是我们经常会遇到的一种列表请求方式,本篇文章将采用浏览器IntersectionObserver API来实现懒加载的请求效果👇👇
Intersection Observer
它是浏览器提供的一种观察者API,提供了一种异步观察目标元素与祖先元素或顶级文档视口的交集变化的方法。
Intersection Observer API 允许代码注册一个回调函数,只要他们希望监视的元素进入或退出另一个元素(或视口),或者当两者相交的数量改变请求的数量时,就会执行该回调函数。这样,站点就不再需要在主线程上做任何事情来监视这种元素交叉点,并且浏览器可以根据需要自由地优化交叉点的管理。
Intersection Observer API 无法告诉您的一件事:重叠像素的确切数量或具体是哪些像素;然而,它涵盖了更常见的用例"如果它们相交大约N %,我需要做一些事情。"
简单一点来讲就是,浏览器可以帮我们监视一个元素和它所在的祖先元素的重叠比例,提供了一个回调函数的入口,方便我们在任意交叉时间节点去做一些事。👀👀
实现原理
那我们如何利用这个特性来实现滚动加载呢?(❁´◡`❁)
例如下面的列表想要在红色框内实现滚动加载,我们可以在列表下方添加一个高度为0的div
的节点(图中黄色框所示),监测这个空白节点是否滚动出现在父容器当中,也就是与父元素产生了视口交集(出现在了父元素的底部),这个时候我们就可以通过回调函数调接口,增加列表长度;
每一次空白div
元素出现在父容器,被我们可视视口捕捉到时,调用数据请求接口,实现滚动加载效果,直至列表数据的返回长度小于指定长度(也就是下一次调用接口就没有数据了)😎
代码实现
在Vue3中的具体实现,结合了vueuse
库,使用之前记得install
一下库👇👇
xml
<script setup lang="ts">
import { useIntersectionObserver } from '@vueuse/core'
const deployList = ref<DeployType[]>([]), //列表数据
pageParams = reactive({
pageNo: 1,
pageSize: 10
})
const target = ref() //目标节点
const isLazy = ref(false) //是否懒加载
const isLazyEnd = ref(false) //是否懒加载结束
//使用vueuse库中封装好的IntersectionObserver
useIntersectionObserver(target, ([{ isIntersecting }]) => {
if (isIntersecting) {
// if (isLazyEnd.value) {
// stop()
// }
isLazy.value = true
}
})
//进行监听
watch(
() => isLazy.value,
() => {
if (isLazy.value && !isLazyEnd.value) {
//如果触发了懒加载,更新数据
pageParams.pageNo++
//发起请求
$api.getDeployList(pageParams).then(res => {
if (res.data.rows.length < pageParams.pageSize) {
// 如果返回的数据小于每页的数据,说明已经到底了,下次请求就没有数据了
isLazyEnd.value = true
}
deployList.value.push(...res.data.rows)
})
isLazy.value = false
}
}
)
// ---------------------- 懒加载请求标志 end----------------------
</script>
<template>
<VCard class="text-left container">
<el-container>
<el-aside width="500px" class="aside">
<el-timeline>
<el-timeline-item
v-for="item in deployList"
:key="item.id"
:timestamp="item.createdAt"
placement="top"
>
xxxx
</el-timeline-item>
</el-timeline>
<div v-if="deployList.length > 9" ref="target"></div>
</el-aside>
<el-main>
xxxx
</el-main>
</el-container>
</VCard>
</template>
大功告成! 撒花🎉🎉🎉