适用场景
intersection表示交叉,指的是两个元素之间有个交叉,Observer表示观察两个元素有没有交叉。
它的适用场景有很多,比如
- 页面滚动过程中的懒加载。
- 长页面无限内容加载。
- 页面中广告查看量的计算。
- 其他需要用户可见才进行的操作,动画等。
用法
初始化监视器
let options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);
使用该 API,有两个角色会参与进来
- 容器(root or root element):缺省或传递 null 时为文档视窗 viewport,否则是指定的元素。
- 目标元素(target):需要监视(observe)的目标元素。
API 会在目标元素可见,即出现在容器中时执行指定的回调。
但回调也不是都执行,它受参数 threshold 的控制。
所以还需要理解一个概念,Intersection Ratio,可理解成目标元素的身体出现在容器中多少时,才触发回调,进一步理解请看下图:
上面 threshold 就是指定 Intersection Ratio 的。它是一个介于 0~1 的小数,默认为 0 ,即一旦可见就执行,1 则表示元素全部可见才执行。
除了将 threshold 指定为数字,还可指定为一个数字的数组,比如 [0, 0.25, 0.5, 0.75, 1],这样在元素出现过程中,其可见范围分别为 0, 25%,50%,75%, 100% 时都会触发一次回调。
而 rootMargin 则用于指定容器的边距,接收的值和 CSS margin 一样。这个边距会在计算目标可见范围时被考虑进去,即在容器原有的内容范围内,减去 margin 的这部分。
执行监视
利用构造器 IntersectionObserver 创建好一个监视器后,便可以对容器内的元素进行监视了。
let target = document.querySelector('#listItem');
observer.observe(target);
回调
回调的结构如下:
let callback = (entries, observer) => {
entries.forEach(entry => {
// Each entry describes an intersection change for one observed
// target element:
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
};
回调的入参为一个 IntersectionObserverEntry 数组,同时还有监视器本身 observer。
一个完整的示例
export default {
install(app) {
app.directive('lazy', {
mounted(el, binding) {
// 创建一个新的Intersection Observer来检测元素何时进入视图:
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
el.src = binding.value
observer.unobserve(el); // 移除监听器以提高性能
}
},{
threshold: 0,
});
// 将该元素添加到观察列表中:
observer.observe(el);
},
})
},
}
运行效果可以查看本站首页,本站首页的懒加载效果就是上面这段代码实现的。
兼容性
虽然是实验性 API,但支持情况还可以。根据 Can I Use #intersectionobserver 的数据,PC 端除 IE 外主流浏览器均已支持,移动端 UC 部分支持,其余浏览器支持良好。
总结
官方说明——《Intersection Observer》
如果本文对你有所帮助,可以帮我点个赞或者请我喝杯奶茶~万分感谢🎉🎉🎉