Intersection Observer 预加载图片不生效是怎么回事?
我在用 Intersection Observer 做图片懒加载,但明明元素进视口了,回调却没触发,图片一直没加载。我检查了 rootMargin 和 threshold,也加了 observer.observe(img),可还是不行。
这是我的 observer 写法:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
}, { threshold: 0.1 });
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
页面结构里 img 确实用了 data-src,但滚动时完全没反应,控制台也没报错,到底哪里漏了?
第一个是浏览器兼容性问题,IntersectionObserver 在老版本 Safari(12.1 之前)或者某些移动端浏览器可能不支持,你可以加个判断看看:
第二个是图片元素本身有没有被渲染出来,比如你是不是把 img 的 display 设成了 none,或者被父元素 overflow: hidden 裁掉了,这种情况下 intersection 根本不会触发,因为元素没在视口里“真正可见”。
第三个是 data-src 里的路径是不是有效的,有时候路径错了或者图片资源根本没加载,浏览器会静默失败,你可以先手动给 img.src 赋值试试看能不能正常显示。
还有一个特别隐蔽的点:你是不是在 observer 创建之前就调用了 observer.observe(img)?虽然你这段代码看起来没问题,但如果 img 元素还没插入 DOM 就去 observe,有些浏览器会直接忽略。
另外建议加个日志确认回调有没有跑进去:
如果加了日志还是没打印,基本就是上面几个环境或结构问题;如果日志有打印但图片没加载,那就是 data-src 的值或者资源本身的问题。
复制这个试试:
如果图片是在某个容器里滚动(比如 #container),那就改成:
另外检查下:
- img 元素有没有 display:none 或 visibility:hidden(这些会让 intersection 为 false)
- data-src 有没有值(控制台打个 log 看看 entry.target.dataset.src 是不是空)
- 页面有没有 overflow: hidden 挡住滚动
再不行加个 console.log(entries) 看回调到底进没进,一般都能定位到问题。