用 Intersection Observer 实现图片懒加载,核心是监听图片是否进入视口并在即将可见时加载真实图片;通过 threshold 设置触发阈值,用 data-src 存真实地址、src 设占位图,回调中赋值后 unobserve,配合 loading="lazy" 降级,旧浏览器可回退 getBoundingClientRect + scroll。

用 Intersection Observer 实现图片懒加载,核心是监听图片元素是否进入视口,只在即将可见时才加载真实图片,避免首屏卡顿和带宽浪费。
创建 Observer 并监听目标元素
先初始化一个 IntersectionObserver 实例,设置触发阈值(如 0.1 表示图片顶部进入视口 10% 就开始加载),然后遍历所有带懒加载标记的 <img> 元素并调用 observe():
- 推荐把真实图片地址存在
data-src属性里,src先设为空或占位图 - 观察器回调中,对每个进入视口的元素,把
data-src赋给src,再调用unobserve()避免重复触发 - 可加简单错误处理:加载失败时 fallback 到占位图或记录日志
HTML 结构要配合标记
每张需要懒加载的图片需有明确标识,常见写法:
<img src="placeholder.svg" alt="描述" class="lazy">
- 不建议用
src="",部分浏览器会发空请求;用小体积占位图更稳妥 - 加上
loading="lazy"作为原生降级(现代浏览器自动处理,不影响 JS 逻辑) - 可统一用
class="lazy"或data-lazy便于 JS 选择
兼容性与性能优化点
Intersection Observer 在主流浏览器中支持良好(Chrome 51+/Firefox 55+/Safari 12.1+),但旧版 iOS Safari 需注意:
- 可加简易降级:检测
IntersectionObserver是否存在,不存在则用getBoundingClientRect()+scroll事件模拟(仅限必要场景) - 避免在滚动中频繁操作 DOM,Observer 本身已做节流,无需额外防抖
- 加载图片后可移除
data-src和class="lazy",方便后续样式或逻辑区分
完整轻量示例代码
以下为可直接使用的最小可行实现:
if ('IntersectionObserver' in window) {
const lazyObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.dataset.src;
if (src) {
img.src = src;
img.removeAttribute('data-src');
lazyObserver.unobserve(img);
}
}
});
}, { threshold: 0.1 });
document.querySelectorAll('img[data-src]').forEach(img => {
lazyObserver.observe(img);
});
}
这段代码不依赖框架,无第三方库,上线即用,兼顾语义、性能和可维护性。


















