IntersectionObserver可以监听一个元素和可视区域相交部分的比例,然后在可视比例达到某个阈值的时候触发回调。非常适合用在于滚动相关的交互事件中,例如:图片懒加载、无限滚动加载等。
用法
new IntersectionObserver(callback, options)
// 创建要观察的目标元素
const targetElement = document.getElementById('target');
// 定义options对象,设置观察环境
const options = {
root: document.querySelector('#scrollArea'),
// 指定根元素,用于检查目标的可见性。必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗。
rootMargin: '0px',
// 使用类似于设置CSS边距的语法来指定根边距(根元素的观察影响范围)
threshold: 0.3
// 阈值,可以是单一的 number 也可以是 number 数组。
// target 元素和 root 元素相交程度达到该值的时候 IntersectionObserver 注册的回调函数将会被执行。
}
// 设置回调函数
const callback =(entries, observer) => {
entries.forEach(entry => {
// 每个成员都是一个IntersectionObserverEntry对象。
// 举例来说,如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员。
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
if(entry.isIntersecting){
// 元素进入可视区
}
});
};
var myObserver = new IntersectionObserver(callback, options)
myObserver.observe(targetElement);
参数和属性
callback:
触发交叉的回调函数,接收一个entries参数,是一个IntersectionObserverEntry对象数组,提供了观察元素的信息,介绍几个常用的属性:
- boundingClientRect:当前观察元素的矩形区域,类似
getBoundingClientRect()
- intersectionRatio:当前元素被交叉的比例。
- intersectionRect:和视区交叉的矩形大小。
- isIntersecting:true表示元素进入可视区内,false反之。
- target:当前交叉的元素。
交叉可以理解为监听的目标元素在视图中可见。 注意:页面初始化的时候会触发一次callback,entries为所有已监听的目标集合
options:
配置项,可选。
- root:监听对象的祖先元素,默认是浏览器窗体元素。
- rootMargin:检测区域的偏移量,默认“0px 0px 0px 0px”上右下左,正数值会增大视图区的检测范围,负值会缩小范围。
例如:设置rootMargin为”20px 0px 30px 30px”,如图此时滚动元素并未到达视窗,但已经切换为可见状态了:
- threshold:阈值数组, 按升序排列, 范围为[0, 1.0]每个阈值都表示监听对象的交叉区域与边界区域的百分比。当监听对象的任何阈值被越过时,都会触发一次callback回调。如果构造器未传入值, 则默认值为0。
方法
IntersectionObserver.disconnect() 停止监听工作。
IntersectionObserver.observe() 开始监听一个目标元素。IntersectionObserver.observe(targetElement);
此元素必须是根元素的后代 (如果根元素为视窗,则该元素必须被当前文档包含)。
IntersectionObserver.takeRecords() 返回所有观察目标的IntersectionObserverEntry对象数组。
IntersectionObserver.unobserve() 停止监听特定目标元素。
示例
图片懒加载
无限滚动加载
兼容性
IE浏览器不兼容,但是官方提供了polyfill
对比scroll事件
相比监听scroll事件,在频繁触发的scroll事件中访问元素的scrollTop、getBoundingClientRect等属性方法会频繁触发回流,非常消耗性能。而IntersectionObserver的回调是异步触发,不会随着目标元素的滚动而触发,性能消耗较低。
注意
IntersectionObserver API 是异步的,不随着目标元素的滚动同步触发。 规格写明,IntersectionObserver的实现,应该采用requestIdleCallback(),即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。
TIPS
在业务中,我们经常会做一些关于埋点上报的需求,比如一些页面展示时上报、按钮点击时上报等等。当需要元素曝光时上报就比较麻烦了,元素层级关系复杂可能会涉及到大量的计算,严重时可能影响页面性能。我们可以用IntersectionObserver解决这个问题。
参考:
https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver
https://juejin.cn/post/6844903926815277069#comment
http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html