最近公司要实现大量数据的列表展示,当然是需要用到懒加载去处理拉,在这里记录一下使用IntersectionObserver这个API去实现的过程
IntersectionObserver 介绍
MDN上的介绍
Intersection Observer API 提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法,Intersection Observer API 会注册一个回调函数,每当被监视的元素进入或者退出另外一个元素时 (或者 viewport ),或者两个元素的相交部分大小发生变化时,该回调方法会被触发执行
注意,初始化监听目标元素时,回调函数就会触发一次
IntersectionObserver 用法
-
创建一个 intersection observer
let observer = new IntersectionObserver(callback [, options]);
- callback - 必要,回调函数
- options - 选填,配置项,允许控制观察者的回调函数的被调用时的环境
options有以下字段:- root 指定根元素,用于检查目标的可见性,必须是目标元素的父级元素,如未指定或为null,则默认为浏览器视窗
- rootMargin 根元素的外边距,类似于 CSS 中的 margin 属性,比如 “10px 20px 30px 40px”,如果有指定 root 参数,也可以使用百分比来取值。该属性值是用作 root 元素和 target 发生交集时候的计算交集的区域范围,使用该属性可以控制 root 元素每一边的收缩或者扩张,默认值为四个边距全是 0
- threshold 可以是单一的 number 也可以是 number 数组,target 元素和 root 元素相交程度达到该值的时候 IntersectionObserver 注册的回调函数将会被执行。如果你只是想要探测当 target 元素的在 root 元素中的可见性超过 50% 的时候,你可以指定该属性值为 0.5。如果你想要 target 元素在 root 元素的可见程度每多 25% 就执行一次回调,那么你可以指定一个数组 [0, 0.25, 0.5, 0.75, 1]。默认值是 0 (意味着只要有一个 target 像素出现在 root 元素中,回调函数将会被执行)。该值为 1.0 含义是当 target 完全出现在 root 元素中时候 回调才会被执行。
例如:
let options = { root: document.querySelector('#scrollArea'), rootMargin: '0px', threshold: 1.0 } let observer = new IntersectionObserver(callback, options);
-
创建一个 observer 后需要给定一个目标元素进行观察
let target = document.querySelector('#listItem'); observer.observe(target);
每当目标满足该 IntersectionObserver 指定的 threshold 值,回调被调用
-
停止观察,关闭观察器
observer.unobserve(target); observer.disconnect();
项目中实现代码
<div
class="load-more"
ref="loadMore"
> 加载中...</div>
---------------------
data(){
return {
observer:null,
isInitListen:false,
accountList:[], // 已加载的数据列表
totalAcount:0, // 数据总数(已加载+未加载)
}
}
// 绑定触底监听事件
bindTouchBottomListener(){
// 创建实例
this.observer = new IntersectionObserver(()=>{
// 阻止初始化时执行回调函数里的逻辑
if(!this.isInitListen){
this.isInitListen = true;
return;
}
if(this.accountList.length < this.totalAcount){
// 获取列表数据
this.getAccountListByFeatId()
}
});
// 获取要观察的dom元素
let elem = this.$refs.loadMore[0];
// 开始观察指定dom元素
elem && this.observer.observe(elem);
this.$once("hook:beforeDestroy",()=>{
// 停止观察
elem && this.observer?.unobserve(elem);
// 关闭观察器
this.observer?.disconnect();
this.observer = null;
})
},