1. 为什么需要 IntersectionObserver?
传统滚动监听(如 scroll
事件)需要频繁计算元素位置,性能差且代码复杂。而 IntersectionObserver 提供了一种异步、高性能的解决方案,专门用于检测目标元素与视口(或父元素)的交叉状态。
2. 核心概念与参数解析
javascript复制代码
ini
const observer = new IntersectionObserver(callback, options);
-
options
配置项:root
:观察的根元素(默认是视口null
)。rootMargin
:扩展/缩小根元素的检测范围(如"10px 20px"
。threshold
:触发回调的交叉比例阈值(如[0, 0.5, 1]
表示 0%、50%、100% 可见时触发)。
-
callback
回调函数 : 接收entries
数组,每个entry
包含:isIntersecting
:目标是否进入视口。intersectionRatio
:当前交叉比例。
3. 经典应用场景与代码实战
场景1:图片懒加载
html复制代码
ini
<img data-src="image.jpg" class="lazy-img">
<script>
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // 替换真实URL
observer.unobserve(img); // 停止观察已加载图片
}
});
}, { threshold: 0.1 }); // 10%可见时触发
document.querySelectorAll('.lazy-img').forEach(img => observer.observe(img));
</script>
原理 :图片进入视口后动态加载 src
,减少首屏请求1[8]。
场景2:无限滚动(加载更多)
javascript复制代码
ini
const sentinel = document.querySelector('#load-more-trigger');
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
fetchMoreData(); // 加载下一页数据
}
}, { rootMargin: '100px' }); // 提前100px触发
observer.observe(sentinel);
优化点 :通过 rootMargin
提前触发,避免用户等待。
场景3:滚动动画触发
css复制代码
css
.hidden { opacity: 0; transform: translateY(20px); }
.visible { opacity: 1; transform: translateY(0); transition: 1s; }
javascript复制代码
ini
const animateOnScroll = (entries) => {
entries.forEach(entry => {
entry.target.classList.toggle('visible', entry.isIntersecting);
});
};
const observer = new IntersectionObserver(animateOnScroll, { threshold: 0.2 });
document.querySelectorAll('.hidden').forEach(el => observer.observe(el));
效果:元素进入视口时触发淡入动画。
4. 注意事项与性能优化
- 异步执行:回调在浏览器空闲时触发,避免阻塞主线程。
- 及时清理 :对不再需要观察的元素调用
unobserve()
或disconnect()
。 - 兼容性 :支持所有现代浏览器,旧版可加 polyfill6。
5. 为什么比传统方法更优?
方法 | IntersectionObserver | scroll 事件 + getBoundingClientRect |
---|---|---|
性能 | ✅ 异步,低开销 | ❌ 同步,高频计算导致卡顿 |
代码复杂度 | ✅ 简洁(10行内搞定) | ❌ 需手动计算位置和节流 |
🚀 动手试试吧! 用 IntersectionObserver
替换你的滚动监听代码,性能提升立竿见影! 讨论点:你在项目中用它解决过哪些问题?欢迎评论区分享~