IntersectionObserver
哈喽,大家好,今天依然是介绍一个新的非常好用并且常用的API,就是IntersectionObserver!那么这个API的作用是什么呢?别急,我们先看实际案例中的需求,向下滚动加载数据。
一般情况下我们是通过计算页面距离来实现向下滚动加载数据。
在这之前我们先了解几个关于页面距离的参数:
document.documentElement.scrollHeight
表示html元素的实际高度,也就是页面的实际高度,这里因为页面的原因,所以无法表示出来,这里只要知道,当页面到最底部时,document.documentElement.scrollHeight = document.documentElement.clientHeight + window.pageYoffset
document.documentElement.clientHeight
页面可视区的高度window.pageYoffset/document.documentElement.scrollTop
表示页面截取的高度,也可以认为是滚动条离页面顶部的距离
关于距离参数详细介绍,可以看这篇博客:传送门
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>IntersectionObserver</title>
<style>
#box {
width: 200px;
height: 200px;
background-color: lightblue;
margin-top: 1000px;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
const el = document.getElementById('box');
const scrollFn = () => {
// 当页面到最底部时,有document.documentElement.scrollHeight = document.documentElement.clientHeight + window.pageYoffset,此时控制台打印123,并且移出监听事件
if (
// 滑动到底部时触发
document.documentElement.scrollHeight - window.pageYOffset ===
document.documentElement.clientHeight
// 滑动到盒子刚进入到可视区时触发,这里不能用 === ,否则滑动速度过快导致无法触发,这是用距离参数计算的缺点
// document.documentElement.scrollHeight - window.pageYOffset <=
// document.documentElement.clientHeight + el.offsetHeight
) {
console.log(123);
window.removeEventListener('scroll', scrollFn);
}
};
// 监听页面滚动
window.addEventListener('scroll', scrollFn);
</script>
</body>
</html>
效果:
这么做的一个缺点就是因为是根据页面的距离参数来计算的,当我们滑动速度过快时,可能无法触发事件。
而对于这个问题,我们就可以用到今天的主角 IntersectionObserver。
-
用法
// 创建观察对象实例 const observer = new IntersectionObserver(callback, options) /* 1. callback - 被观察DOM元素进入或离开可视区时触发的回调函数 callback回调函数中有两个回调参数 - entries 被观察的元素信息对象的数组 [{isIntersecting}] 解构的isIntersecting,判断进入或离开,其他属性见下面的表格 - observer 观察实例 2. options配置项 见表格 3. 实例提供两个常用方法 其余方法见表格 observer.observe(DOM) 观察哪个DOM observer.unobserve(DOM) 停止观察哪个DOM */
- entries数组对象中的属性
属性 说明 boundingClientRect 返回包含目标元素的边界信息,返回结果与element.getBoundingClientRect() 相同 intersectionRatio 返回目标元素出现在可视区的比例 范围0-1 intersectionRect 用来描述root和目标元素的相交区域 isIntersecting 返回一个布尔值,下列两种操作均会触发callback:1. 如果目标元素出现在root可视区,返回true。2. 如果从root可视区消失,返回false rootBounds 用来描述交叉区域观察者(intersection observer)中的根 target 目标元素:与根出现相交区域改变的元素 (Element) time 返回一个记录从 IntersectionObserver 的时间原点到交叉被触发的时间的时间戳 表格中加粗的两个属性是比较常用的判断条件:isIntersecting和intersectionRatio
- options配置项
属性 说明 root 基于的滚动容器,默认是document rootMargin 计算交叉时添加到根(root)边界盒bounding box的矩形偏移量, 可以有效的缩小或扩大根的判定范围从而满足计算需要。所有的偏移量均可用像素( px
)或百分比(%
)来表达, 默认值为"0px 0px 0px 0px"threshold 一个包含阈值的列表, 按升序排列, 列表中的每个阈值都是监听对象的交叉区域与边界区域的比率。当监听对象的任何阈值被越过时,都会触发callback。默认值为0,范围0-1。0表示被观察的DOM元素刚进入到可视区触发回调,1表示被观察的DOM元素完全进入到可视区触发回调 - 实例提供的方法
方法 说明 onserve(DOM) 开始监听一个目标元素 unobserve(DOM) 停止监听特定目标元素 takeRecords() 返回所有观察目标的IntersectionObserverEntry对象数组 disconnect() 使IntersectionObserver对象停止全部监听工作 -
应用——数据懒加载
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>IntersectionObserver</title> <style> #box { width: 200px; height: 200px; background-color: lightblue; margin-top: 1000px; } </style> </head> <body> <div id="box"></div> <script> const el = document.getElementById('box') const observer = new IntersectionObserver(([{isIntersecting}]) => { if (isIntersecting) { // DOM元素进入可视区 observer.unobserve(el) // 结束监听 console.log(123); } }, { threshold: 0 }) // 开始监听 observer.observe(el) </script> </body> </html>
-
效果
-
优势
-
他解决了前面所说的问题,当我们滑动速度过快时,可能无法触发事件。
-
在当前判断可视性的方法,基本就是监听
scroll
事件,但是由于其高频的计算频率,会导致浏览器性能的损失,尤其是,如果一个同一个页面中,有多个地方,需要这样的判断,那么就需要绑定多个scroll
事件,或者有多个计时器在轮询的话,那么对性能的损失就更为客观了。因此相比之下,该API可以节约性能。
-
-
兼容性问题
可以看到目前已经兼容大多数主流浏览器。
-