用intersectionobserver实现图片懒加载的核心是不监听scroll事件、不频繁触发重排重绘、只在图片即将进入视口时加载;通过data-src存地址、rootmargin提前加载、onerror降级、srcset/sizes延迟写入及img.decode()异步解码,兼顾性能与健壮性。

用 IntersectionObserver 实现图片懒加载,核心是**不监听 scroll 事件、不频繁触发重排重绘、只在图片即将进入视口时才开始加载**。它天然规避了传统 scroll + getBoundingClientRect 方案的性能陷阱。
基础实现:监听图片进入视口并替换 src
关键点在于:给 <img> 设置 data-src 存真实地址,初始 src 留空或指向占位图;观察器回调中批量处理可见项,仅对尚未加载的图片设置 src 并取消观察(避免重复触发)。
- 创建 observer 时传入
{ rootMargin: '50px' },让图片提前 50px 开始加载(防滚动过快导致白屏) - 调用
observer.observe(img)注册每张图片,不要一次性 observe 所有 img 后再遍历——应逐个绑定 - 回调中用
entries.forEach(entry => { if (entry.isIntersecting) { ... } })判断是否可见 - 加载成功后调用
observer.unobserve(entry.target),释放资源
增强健壮性:处理加载失败与降级
网络异常或 404 会导致图片加载失败,此时应有 fallback 行为,避免长期空白。
- 为
<img>绑定onerror事件,失败时显示占位文案或备用图:img.onerror = () => img.src = '/placeholder.svg' - 对已加载过的图片跳过再次 observe(可加自定义属性如
data-loaded="true"做标记) - 若 JS 未执行或被禁用,可在 HTML 中保留
<noscript><img src="..."></noscript>作为服务端降级
进一步优化:响应式图片 + 解码控制
懒加载时若直接写死 src,会忽略设备像素比和屏幕宽度。应结合 srcset 和 sizes,并延迟解码以减少主线程压力。
- 把
srcset和sizes也存在data-*属性里,加载时一并写入:img.srcset = img.dataset.srcset; img.sizes = img.dataset.sizes - 加载后调用
img.decode().catch(() => {})异步解码,防止渲染阻塞(现代浏览器支持) - 对
<picture></picture>结构,需递归处理内部<source></source>标签的data-srcset
兼容性与初始化策略
IE 完全不支持 IntersectionObserver,但无需立即 polyfill——可先检测 API 是否可用,不可用时退回到简单 onload 或 scroll 检测(仅低频触发)。
- 初始化前判断:
if ('IntersectionObserver' in window),否则用轻量级 fallback - 避免在 DOMContentLoaded 之前执行 observe,确保所有目标 img 已挂载
- 若页面动态插入图片(如无限滚动),每次新增后调用
observer.observe(newImg)即可,无需重建 observer
整个过程不依赖定时器、不读取元素几何属性、不触发 layout,CPU 占用接近于零。只要注意取消观察和错误处理,就能做到真正“极低损耗”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











