We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
网页开发时,不管是在移动端,还是PC端,都有个很重要的概念,叫做动态懒加载,适用于一些图片资源(或者数据)特别多的场景中,这个时候,我们常常需要了解某个元素是否进入了“视口”(viewport),即用户能不能看到它。
传统的实现方法是,监听到scroll事件或者使用setInterval来判断,调用目标元素的getBoundingClientRect()方法,得到它对应于视口左上角的坐标,再判断是否在视口之内。这种方法的缺点是,由于scroll事件触发频率高,计算量很大,如果不做防抖节流的话,很容易造成性能问题,而setInterval由于其有间歇期,也会出现体验问题。
scroll
setInterval
getBoundingClientRect()
所以在几年前,Chrome率先提供了一个新的API,就是IntersectionObserver,它可以用来自动监听元素是否进入了设备的可视区域之内,而不需要频繁的计算来做这个判断。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"。
API
IntersectionObserver
由于这个api问世已经很多年了,所以对浏览器的支持性还是不错的,完全可以上生产环境,点击这里可以看看当前浏览器对于IntersectionObserver的支持性:
点击这里
该API的调用非常简单:
const io = new IntersectionObserver(callback, option);
上面代码中,IntersectionObserver 是浏览器原生提供的构造函数,接受两个参数:
callback
option
构造函数的返回值是一个观察器实例。实例一共有4个方法:
observe
unobserve
disconnect
takeRecords
该方法需要接收一个target参数,值是Element类型,用来指定被监听的目标元素
// 获取元素 const target = document.getElementById("dom"); // 开始观察 io.observe(target);
该方法需要接收一个target参数,值是Element类型,用来指定停止监听的目标元素
// 获取元素 const target = document.getElementById("dom"); // 停止观察 io.unobserve(target);
该方法不需要接收参数,用来关闭观察器
// 关闭观察器 io.disconnect();
该方法不需要接收参数,返回所有被观察的对象,返回值是一个数组
// 获取被观察元素 const observerList = io.takeRecords();
observe方法的参数是一个 DOM 节点,如果需要观察多个节点,就要多次调用这个方法:
// 开始观察多个元素 io.observe(domA); io.observe(domB); io.observe(domC);
目标元素的可见性变化时,就会调用观察器的回调函数callback。
callback一般会触发两次。一次是目标元素刚刚进入视口,另一次是完全离开视口。
const io = new IntersectionObserver((changes, observer) => { console.log(changes); console.log(observer); });
上面代码中,callback函数的参数接收两个参数changes和observer:
changes
observer
changes[0]
上面提到的changes数组中的每一项都是一个IntersectionObserverEntry 对象(下文简称io对象),对象提供目标元素的信息,一共有八个属性,我们打印这个对象:
// 创建实例 const io = new IntersectionObserver(changes => { changes.forEach(change => { console.log(change); }); }); // 获取元素 const target = document.getElementById("dom"); // 开始监听 io.observe(target);
运行上面代码,并且改变dom的可见性,这时控制台可以看到一个对象:
每个属性的含义如下:
boundingClientRect
intersectionRatio
intersectionRect
1
0
isIntersecting
isVisible
rootBounds
null
target
time
预加载(滚动加载,翻页加载,无限加载)
懒加载(后加载、惰性加载)
其它
IntersectionObserver API 是异步的,不随着目标元素的滚动同步触发。
规格写明,IntersectionObserver的实现,应该采用requestIdleCallback(),即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。
requestIdleCallback()
The text was updated successfully, but these errors were encountered:
No branches or pull requests
1. 背景
网页开发时,不管是在移动端,还是PC端,都有个很重要的概念,叫做动态懒加载,适用于一些图片资源(或者数据)特别多的场景中,这个时候,我们常常需要了解某个元素是否进入了“视口”(viewport),即用户能不能看到它。
传统的实现方法是,监听到
scroll
事件或者使用setInterval
来判断,调用目标元素的getBoundingClientRect()
方法,得到它对应于视口左上角的坐标,再判断是否在视口之内。这种方法的缺点是,由于scroll
事件触发频率高,计算量很大,如果不做防抖节流的话,很容易造成性能问题,而setInterval
由于其有间歇期,也会出现体验问题。所以在几年前,Chrome率先提供了一个新的
API
,就是IntersectionObserver
,它可以用来自动监听元素是否进入了设备的可视区域之内,而不需要频繁的计算来做这个判断。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"。2. 兼容性
由于这个api问世已经很多年了,所以对浏览器的支持性还是不错的,完全可以上生产环境,
点击这里
可以看看当前浏览器对于IntersectionObserver
的支持性:3. 用法
该
API
的调用非常简单:上面代码中,
IntersectionObserver
是浏览器原生提供的构造函数,接受两个参数:callback
:可见性发现变化时的回调函数option
:配置对象(可选)。构造函数的返回值是一个观察器实例。实例一共有4个方法:
observe
:开始监听特定元素unobserve
:停止监听特定元素disconnect
:关闭监听工作takeRecords
:返回所有观察目标的对象数组3.1 observe
该方法需要接收一个target参数,值是Element类型,用来指定被监听的目标元素
3.2 unobserve
该方法需要接收一个target参数,值是Element类型,用来指定停止监听的目标元素
3.3 disconnect
该方法不需要接收参数,用来关闭观察器
3.4 takeRecords
该方法不需要接收参数,返回所有被观察的对象,返回值是一个数组
注意:
observe
方法的参数是一个 DOM 节点,如果需要观察多个节点,就要多次调用这个方法:4. callback 参数
目标元素的可见性变化时,就会调用观察器的回调函数
callback
。callback
一般会触发两次。一次是目标元素刚刚进入视口,另一次是完全离开视口。上面代码中,
callback
函数的参数接收两个参数changes
和observer
:changes
:这是一个数组,每个成员都是一个被观察对象。举例来说,如果同时有两个被观察的对象的可见性发生变化,那么changes
数组里面就会打印出两个元素,如果只观察一个元素,我们打印changes[0]
就能获取到被观察对象observer
: 这是一个对象,返回我们在实例中传入的第二个参数option(如果没传,则返回默认值)5. IntersectionObserverEntry 对象
上面提到的changes数组中的每一项都是一个IntersectionObserverEntry 对象(下文简称io对象),对象提供目标元素的信息,一共有八个属性,我们打印这个对象:
运行上面代码,并且改变dom的可见性,这时控制台可以看到一个对象:
每个属性的含义如下:
boundingClientRect
:目标元素的矩形区域的信息intersectionRatio
:目标元素的可见比例,即intersectionRect
占boundingClientRect
的比例,完全可见时为1
,完全不可见时小于等于0
intersectionRect
:目标元素与视口(或根元素)的交叉区域的信息isIntersecting
: 布尔值,目标元素与交集观察者的根节点是否相交isVisible
: 布尔值,目标元素是否可见(该属性还在试验阶段,不建议在生产环境中使用)rootBounds
:根元素的矩形区域的信息,getBoundingClientRect()
方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
target
:被观察的目标元素,是一个 DOM 节点对象time
:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒6. 应用
预加载(滚动加载,翻页加载,无限加载)
懒加载(后加载、惰性加载)
其它
7. 注意点
IntersectionObserver API 是异步的,不随着目标元素的滚动同步触发。
规格写明,
IntersectionObserver
的实现,应该采用requestIdleCallback()
,即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。8. 参考链接
The text was updated successfully, but these errors were encountered: