以前做懒加载靠监听 scroll 事件 + getBoundingClientRect,频繁触发回流,性能差。IntersectionObserver 是浏览器原生提供的交叉观察器,性能好太多。
图片懒加载
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
}, {
rootMargin: '100px 0px',
threshold: 0
});
document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));
rootMargin 提前 100px 开始加载,用户体验更顺。加载完 unobserve,避免重复触发。
曝光埋点
曝光埋点要求「元素出现在视口内一定时间」才算曝光。可以配合 setTimeout。
const exposeObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
el._timer = setTimeout(() => {
reportExpose(el.dataset.id);
exposeObserver.unobserve(el);
}, 1000);
} else {
clearTimeout(entry.target._timer);
}
});
}, { threshold: 0.5 });
注意事项
- threshold 0.5 表示元素一半可见才算,按业务调
- 快速滚动时 isIntersecting 可能闪断,用定时器兜底
- SPA 里组件销毁记得 unobserve,否则内存泄漏
- 老浏览器(IE)不支持,需要 polyfill 或降级到 scroll 方案
这个 API 现在兼容性已经很好了,能用就用,比手写 scroll 监听省心。

Comments 3 条评论
曝光埋点卡时间这个思路好
快速滚动时 isIntersecting 会抖
比监听 scroll 省心多了