今天来给大家介绍一个超实用的API——IntersectionObserver。它就像一个"元素观察者",能帮我们轻松判断元素是否进入视窗,彻底解决传统滚动监听的性能问题。
一、IntersectionObserver 是什么?
简单来说,IntersectionObserver 是浏览器原生提供的一个 观察者API ,用于监测目标元素与其祖先元素或视口的交叉状态。直白点讲:它能告诉你一个元素是否出现在屏幕上,以及出现了多少。
二、为什么要用它?传统方案有什么问题?
以前我们监测元素是否可见,通常会用 scroll 事件 + getBoundingClientRect() :
window.addEventListener('scroll', () => {
const rect = element.getBoundingClientRect();
const isVisible = rect.top < window.innerHeight && rect.bottom >= 0;
// 处理逻辑
});
这种方式有两个致命问题:
-
性能差 :scroll事件触发频率极高,会造成大量计算
-
不精确 :需要手动计算元素位置,容易出错 而 IntersectionObserver 完美解决了这些问题:
- 浏览器原生优化,性能更好
- 自动监听元素可见性变化
- 异步执行,不会阻塞主线程
三、实战案例:项目中的两个经典应用
案例1:瀑布流无限滚动加载
在我们项目的 Waterfall.jsx
(瀑布流) 组件中,IntersectionObserver 被用来实现无限滚动:
// 创建观察者实例
const observer = new IntersectionObserver(([entry], obs) => {
if (entry.isIntersecting) {
fetchMore(); // 当加载元素可见时,触发加载更多
}
});
// 监听加载元素
if(loader.current) observer.observe(loader.current);
// 组件卸载时断开监听
return () => observer.disconnect();
- 创建一个观察者,监听底部的"加载中..."元素
- 当这个元素进入视窗(
isIntersecting
为true
),就调用fetchMore()
加载更多数据 - 组件卸载时,断开监听避免内存泄漏
案例2:图片懒加载
在 ImageCard
(图片展示)组件中,IntersectionObserver
被用来实现图片懒加载:
const observer = new IntersectionObserver(([entry], obs) => {
if(entry.isIntersecting) {
const img = entry.target;
const oImg = document.createElement('img');
oImg.src = img.dataset.src; // 预加载图片
oImg.onload = function() {
img.src = img.dataset.src; // 图片加载完成后显示
}
obs.unobserve(img); // 加载完成后停止观察
}
})
if(imgRef.current) {
observer.observe(imgRef.current);
}
这段代码的工作原理:
- 页面初始化时,图片只设置
data-src
属性,不设置src
- 当图片进入视窗时,创建新图片对象加载真实图片
- 图片加载完成后,才设置到真实的 img 元素上
- 加载完成后,调用
unobserve
停止观察,避免重复加载
四、IntersectionObserver 基本语法
// 创建观察者
const observer = new IntersectionObserver(callback, options);
// 开始观察元素
observer.observe(element);
// 停止观察特定元素
observer.unobserve(element);
// 停止所有观察
observer.disconnect();
callback 回调函数
function callback(entries, observer) {
entries.forEach(entry => {
// entry.isIntersecting: 元素是否可见
// entry.intersectionRatio: 可见比例 (0-1)
// entry.target: 被观察的元素
// ...
});
}
options 配置选项
const options = {
root: null, // 观察的根元素,默认为视口
rootMargin: '0px', // 根元素的边距
threshold: 0.1 // 可见比例达到 10% 时触发回调
};
五、注意事项与小技巧
-
浏览器兼容性 :IE 不支持,需要使用 polyfill
-
避免过度使用 :每个观察者实例最好观察多个元素,而不是创建多个观察者
-
性能优化 :
- 不需要观察时,及时调用
unobserve
或disconnect
- 合理设置
threshold
,避免过于频繁的回调
- 不需要观察时,及时调用
-
图片懒加载最佳实践 :
- 给图片设置默认占位图
- 使用
data-src
存储真实图片地址 - 加载完成后记得停止观察
六、总结
IntersectionObserver
是一个超实用的 API,它让元素可见性监测变得简单高效。无论是无限滚动、图片懒加载,还是埋点统计、广告曝光监测,都能轻松应对。
如果你还在使用传统的 scroll
事件监听元素可见性,赶紧试试 IntersectionObserver
吧!它会让你的代码更简洁、性能更好。