Intersection Observer 是浏览器原生异步 API,用于监听目标元素与视口或祖先容器的交叉状态变化;它不依赖 scroll 事件,避免强制布局和性能抖动,由浏览器在空闲时批量回调,更高效可靠。

Intersection Observer 是什么,为什么不用 scroll 事件
它是一个浏览器原生 API,用来异步观察目标元素与视口(或指定祖先容器)的交叉状态变化。IntersectionObserver 不依赖 scroll 或 resize 事件,避免了频繁触发、强制同步布局(layout thrashing)和性能抖动。滚动监听需要手动节流、计算元素位置、反复调用 getBoundingClientRect(),而 IntersectionObserver 由浏览器在渲染帧空闲时批量回调,更轻量、更可靠。
如何创建并监听一个懒加载目标元素
核心是把待懒加载的元素(比如 )传给 observe(),并在回调中检查其 isIntersecting 状态:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img); // 加载完就停止观察
}
});
});
document.querySelectorAll('img.lazy').forEach(img => {
observer.observe(img);
});
-
entry.isIntersecting为true表示元素至少有一像素进入视口,是最常用的判断依据 - 务必在加载完成后调用
observer.unobserve(el),否则同一元素可能被重复触发 - 不要在回调里直接操作 DOM 样式(如
img.style.display = 'block')来“显隐”,应优先用 CSS 类控制,避免阻塞渲染
常见懒加载失败原因:rootMargin 和 threshold 怎么设
默认情况下,IntersectionObserver 只在元素真正进入视口时才触发,但用户往往希望「提前一点」加载,避免滚动过快时出现空白。这时靠两个配置项:
-
rootMargin: '0px 0px 200px 0px':等价于 CSS 的 margin,在视口底部扩展 200px 观察区域,让元素还没完全进屏就触发加载 -
threshold: [0, 0.1, 0.5, 1]:指定多个触发比例阈值;例如0.1表示元素 10% 高度可见时就回调,适合长图或卡片列表 - 如果设了
rootMargin却没生效,检查父容器是否设置了overflow: hidden或未设position,导致root计算异常
兼容性与降级处理要点
IntersectionObserver 在现代浏览器中支持良好(Chrome 51+、Firefox 55+、Safari 12.1+),但 IE 完全不支持。若需兼容旧环境:
- 用
typeof IntersectionObserver !== 'undefined'判断是否可用,不可靠写法是if (window.IntersectionObserver)(Safari 早期版本会暴露构造函数但实际不可用) - 降级方案别硬写 scroll 监听:推荐用
lozad.js这类轻量库,或至少封装一个带防抖 +requestIdleCallback的 fallback - 服务端渲染(SSR)场景下,注意首次加载时元素可能已“在视口内”,但 JS 尚未执行,此时需预留
loading="lazy"或服务端预判逻辑
真正容易被忽略的是 rootMargin 的单位必须带 px/em/%,漏写单位会导致整个 observer 失效且无报错;另外,动态插入的懒加载元素,必须在插入 DOM 后再调用 observe(),不能只靠初始化时的一次遍历。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











