前言
作为一个前端搬砖仔,偶尔会遇到关于视窗的问题...
其中就经常会遇到一些数据上报问题,比如某某组件是否被用户看到了,如果看到就要上报数据,让产品同学方便进行数据分析。
分析这个场景可以发现,必须要用户看到了我才能上报,怎么判断用户是否看到了这个组件呢?
传统的方法是操作dom,通过这些数据或方法(offsetTop、scrollTop,getBoundingClientRect)来进行比较。
频繁的对DOM状态的计算,会造成不小的性能损耗,导致页面卡顿。
接下来介绍一种我最近比较常用的新方式:Intersection Observer(交叉观察器)
Intersection Observer 翻译过来即交叉观察器
主要是用于监听目标元素与指定的元素视窗是否发生交叉
一句话总结:Intersection Observer API 提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法。 – MDN
使用
一、利用IntersectionObserver构造函数创建一个观察器实例
<template>
<div class="home"></div>
</template>
<script>
export default {
name: "HomeView",
mounted() {
// 可见性发生变化后的回调
function callback() {
console.log("触发了");
}
// 交叉观察器配置项
let options = {};
// 生成交叉观察器
const observer = new IntersectionObserver(callback);
},
};
</script>
(callback是当元素可见比例超过指定阈值后会调用的一个回调函数,options是一个可以用来配置 observer 实例的对象。)
输出一下IntersectionObserver构造函数返回的实例
实例属性:
root:root 属性用来获取当前 intersectionObserver 实例的根元素,用于判断元素是否可见区域。
(注:这个既可以是 target 元素祖先元素也可以是指定 null 则使用浏览器视口 做为容器 (root)。)
rootMargin:一个类似于margin的字符串参数,就可以使用 root margin 来调整根矩形大小。
(注:由于使用Intersection Observer的过程中所有区域均被当做一个矩形看待,因此当我们需要调整元素边界的矩形时,用 root margin 来调整大小。)
threshold:阈值,可以传一个0 ~ 1的number,也可以传个0 ~ 1范围的number数组。
(注:如果传一个0 ~ 1的number,如0.5则说明,目标元素和root相交超过50%时,即二者重合超过目标元素的50%时,触发回调,如果是一个数组[0.1, 0.2, 0.5]则分别在10% 20% 50%处触发回调)
二、观察器实例监听元素相交
<template>
<div class="home">
<div id="target" class="target-item"></div>
</div>
</template>
<script>
export default {
name: "HomeView",
mounted() {
// 可见性发生变化后的回调
function callback(data) {
console.log("触发了");
console.log(data);
}
// 交叉观察器配置项
let options = {};
// 生成交叉观察器
const observer = new IntersectionObserver(callback);
// 获取目标节点
let target = document.getElementById("target");
// 监听目标元素
observer.observe(target);
},
};
</script>
<style scoped>
.home {
height: 300vh;
}
.home .target-item {
margin-top: 120vh;
width: 20px;
height: 20px;
background: #000;
}
</style>
可以看到
通过滚动,可以不停监听到观察器的回调。
三、观察器回调函数参数
看到在观察器的回调中是返回了一个对象的,修改原来的回调函数,对应看看到底返回了啥?
export default {
name: "HomeView",
mounted() {
// 可见性发生变化后的回调
function callback(data) {
console.log("触发了");
data.map((item) => {
// 目标元素的getBoundingClientRect的返回值。
console.log(item.boundingClientRect);
// 目标元素和根元素交叉区域的getBoundingClientRect的返回值。
console.log(item.intersectionRatio);
// 目标元素的可见比例,相当于二者重合了多少。
console.log(item.intersectionRect);
// 目标元素与根元素是否相交
console.log(item.isIntersecting);
// 根元素的getBoundingClientRect的返回值
console.log(item.rootBounds);
// 目标元素,是个dom
console.log(item.target);
// 从首次创建观察者到触发指定阈值发生交叉的时间
console.log(item.time);
});
}
// 交叉观察器配置项
let options = {
threshold: 0.5,
};
// 生成交叉观察器
const observer = new IntersectionObserver(callback, options);
// 获取目标元素
let target = document.getElementById("target");
// 监听目标元素
observer.observe(target);
},
};
可以看到控制台输出了下述内容:
可以看到返回了很多东西
其中就有我们熟悉的元素的getBoundingClientRect属性。
回调参数属性:
boundingClientRect: 对象,返回了目标元素的getBoundingClientRect的返回值。
intersectionRatio:对象,返回了目标元素和根元素交叉区域的getBoundingClientRect的返回值。
intersectionRect: 数字,目标元素的可见比例,相当于二者重合了多少。
isIntersecting: 布尔值,目标元素与根元素相交是否相交
(如果相交,则返回 true ,若为true则说明至少到达了一个阈值,如果为false,说明目标元素在阈值范围内不可见)
rootBounds: 对象,返回了根元素的getBoundingClientRect的返回值。
target:对象,目标元素,是个dom
time: 数字,从首次创建观察者到触发指定阈值发生交叉的时间
因此通过观察器的回调参数可以做到精确监听目标的,通过这些参数可以更好的支持如下拉加载技术上报等场景,由于该属性是原生api因此比起频繁的操作dom会来的更丝滑。
四、观察器的实例方法
通过上文我们已经说明了,如何使用交叉观察器,并介绍了观察器的实例属性及回调参数
下面说一下观察器的实例方法!
// 生成交叉观察器
const observer = new IntersectionObserver(callback, options);
// 获取目标元素
let target = document.getElementById("target");
// 监听目标元素
observer.observe(target);
可以看到监听目标元素的时候用了 observe 方法,这就是观察器的实例方法之一—— 监听目标元素
观察器的实例方法一共有四个
disconnect:停止对所有的目标元素的观察
observe:监听目标元素(可监听多个)
takeRecords:返回一个IntersectionObserverEntry对象数组(观察器回调参数就是这个),里面存放的各个目标元素的相交信息
unobserve:停止对一个指定目标元素的观察
通过代码来演示下上述方法:
<template>
<div class="home">
<div id="target1" class="target1-item"></div>
<div id="target2" @click="unobserve()" class="target2-item"></div>
<div style="margintop: 10px" @click="disconnect">disconnect</div>
</div>
</template>
<script>
export default {
name: "HomeView",
data() {
return {
observer: {},
};
},
mounted() {
// 可见性发生变化后的回调
function callback(data) {
console.log(data[0].target.id);
}
// 生成交叉观察器
this.observer = new IntersectionObserver(callback);
// 获取目标元素1
let target1 = document.getElementById("target1");
// 获取目标元素2
let target2 = document.getElementById("target2");
// 监听目标元素1
this.observer.observe(target1);
// 监听目标元素2
this.observer.observe(target2);
},
methods: {
unobserve() {
let target2 = document.getElementById("target2");
// 停止监听目标元素2
this.observer.unobserve(target2)
},
disconnect() {
// 停止监听所有目标元素
this.observer.disconnect();
},
},
};
</script>
代码效果如下所示:
可以看到一开始是监听元素1和元素2,接着停止元素2的监听,最后停止所有元素的监听
以上就是Intersection Observer(交叉观察器)的基本使用了。
五、总结
(1)利用IntersectionObserver构造函数创建一个观察器实例,设置其回调和基本参数
// 可见性发生变化后的回调
function callback() {
}
// 生成交叉观察器
this.observer = new IntersectionObserver(callback);
(2)获取目标元素节点,并监听该元素
// 获取目标元素
let target = document.getElementById("target");
// 监听目标元素
this.observer.observe(target);
(3)回调中处理相关逻辑
function callback(data) {
console.log(data)
}
(4)观察器使用结束后,取消对元素的监听
// 停止观察某个目标元素
observer.unobserve(target);
// 关闭监视器
observer.disconnect();
聊聊Intersection Observer各大浏览器的支持性 截图自
总的来说,这个还是适用于很多浏览器的。
各位前端朋友,如果以后有遇到下拉加载或数据上报的场景的话不妨使用一下这个Intersection Observer
确实是一个开发的好工具。
以上就是Intersection Observer交叉观察器示例解析的详细内容,更多关于Intersection Observer交叉观察器的资料请关注编程网其它相关文章!