JavaScript图片懒加载核心是监听图片是否进入视口后才加载真实资源,推荐用IntersectionObserver实现提前加载,不支持时降级为scroll+getBoundingClientRect,并需处理加载失败、布局偏移等优化。
JavaScript 实现图片懒加载,核心是监听图片是否进入视口(viewport),并在进入时才加载其真实图片资源。这能显著减少首屏请求、节省带宽、提升页面初始渲染性能。
使用 IntersectionObserver 监听图片是否进入视口
现代推荐方式是使用 IntersectionObserver API,它原生支持异步监听元素与视口的交叉状态,性能好、写法简洁、无需频繁监听 scroll 或 resize。
- 将图片的真实地址(如
data-src)暂存于自定义属性中,src先设为空或占位图 - 创建 Observer 实例,配置
rootMargin(如"100px")可实现“提前加载”,让图片在真正进入视口前就开始请求 - 回调中判断
isIntersecting === true,则设置img.src = img.dataset.src,并可调用unobserve()避免重复触发
兼容性处理:不支持 IntersectionObserver 时降级为 scroll + getBoundingClientRect
对于需兼容 IE 或老版本浏览器的场景,可用传统方式模拟:
- 将所有待懒加载图片缓存到数组中,绑定
scroll和resize事件(注意节流) - 遍历图片,调用
element.getBoundingClientRect()获取其相对于视口的位置 - 判断
rect.top 0(即顶部在视口下方、底部在视口上方),满足即加载 - 加载后从缓存数组中移除该元素,避免重复检查
HTML 结构与基础 JS 示例
结构示例:
@@##@@
简单 Observer 实现:
const lazyImages = document.querySelectorAll('img.lazy');
if ('IntersectionObserver' in window) {
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);
}
});
}, { rootMargin: '50px' });
lazyImages.forEach(img => observer.observe(img));
}
补充细节与优化建议
实际项目中还需注意:
- 加载失败时提供 fallback,例如监听
img.onerror后显示默认图或错误提示 - 配合
loading="lazy"HTML 属性(现代浏览器原生懒加载),作为兜底或简化静态资源处理 - 若图片有宽高比要求,建议提前设置
width/height或使用 aspect-ratio,防止加载时布局偏移(CLS) - 服务端可结合
Client-Hints(如DPR、Width)动态返回适配尺寸的图片,进一步优化懒加载效果

rsectionObserver实现提前加载,不支持时降级为scroll+getBoundingClientRect,并需处理加载失败、布局偏移等优化。






