一文搞懂图片懒加载
在前端性能优化中,图片往往是“页面加载慢”的罪魁祸首。
图片懒加载(Lazy Load)很好地解决了这个问题,它是一种按需加载资源的前端性能优化策略。
简单来说,就是——只加载用户当前可见区域(首屏)内的图片,而屏幕外的图片在用户滚动到时才加载。
一、什么是图片懒加载?
举个例子
假设有一个包含上百张图片的长网页(比如摄影网站),如果一次性全部请求这些图片,会造成以下题:
- 首屏加载时间过长:需要一次性加载所有图片;
- 占用大量带宽资源;
- 浪费资源:用户可能根本不滚动到底部。
而懒加载可以有效解决以上问题
二、图片懒加载的原理
懒加载的核心思想是:
“等图片要显示了再加载”
实现步骤如下:
1. 初始状态
- 图片不直接加载真实资源
- 使用占位图或留空
src作为默认展示 - 真正图片地址存放在
data-src属性
<img data-src="real.jpg" src="placeholder.jpg" alt="lazy image">
2. 监听页面滚动或可视区域变化
- 通过
IntersectionObserver或scroll事件判断图片是否进入视口。
3.触发加载
- 一旦图片进入视口,将data-src的值赋给src,浏览器便会发起加载请求。
4.完成替换
- 图片加载完成后,可移除
data-src属性,或添加动画过渡效果。
三、两种常见的实现方式
方法一:IntersectionObserver(推荐)
现代浏览器支持的原生API,性能优秀且使用简单
<img data-src="https://example.com/pic.jpg" alt="lazy" class="lazy">
//获取所有带有.lazy的图片
const imgs=document.querySelectorAll('img.lazy')
//创建IntersectionObserver实例
const observer=new IntersectionObserver((entries,obs)=>{
entries.forEach(entry=>{
//判断图片是否进入可视区
if(entry.isIntersecting){
const img=entry.target
//将真实地址赋给src
img.src=img.dataset.src
//移除lazy类
img.classList.remove('lazy')
// 6. 加载完成后取消观察,提升性能
obs.unobserve(img)
}
})
})
//监听每张照片
imgs.forEach(item=>observer.observe(img))
优点:
- 不需要监听滚动事件,性能好;
- 浏览器原生优化,可节流;
- 代码简洁;
缺点:
- 兼容性有限,比如IE不支持,需要polyfill解决。
方法二:scroll+元素位置计算(兼容方案)
//定义懒加载函数
function lazyLoad(){
//获取所有未加载真实图片的img
const imgs=document.querySelectorAll('img[data-src]')
//获取可视区域高度
const viewHeight=window.innerHeight||document.documentElement.clientHeight
imgs.forEach(img=>{
//获取元素相对于视口的位置
const rect=img.getBoundingClientRect()
//判断图片是否进入可视区
if(rect.top<viewHeight){
//赋值真实图片
img.src=img.dataset.src
//移除该属性
img.removeAttribute('data-src')
}
})
}
//监听滚动和页面加载
window.addEventListener('scroll',lazyLoad)
window.addEventListener('load',lazyLoad)
//防抖优化
let timer=null
window.addEventListener('scroll',()=>{
if(timer) clearTimeout(timer)
timer=setTimeout(lazyLoad,200)
})
缺点:
- 频繁触发
scroll,性能差; - 需手动节流/防抖优化;
- 代码量多
所以一般建议加一个防抖函数
四、现代浏览器的懒加载属性(最简单)
现在几乎所有现代浏览器都支持:
<img src="image.jpg" loading="lazy" alt="...">
浏览器会自动在图片进入可视区前加载。
✔ 无需 JavaScript
✔ 原生支持
❌ 兼容性仍需注意(部分旧版 Safari)
六、懒加载的实战优化技巧
| 优化点 | 说明 |
|---|---|
| 使用低质量占位图(LQIP) | 在真实图片加载前显示模糊缩略图,改善视觉体验 |
| 添加加载动画 | 图片加载中可显示 loading 效果 |
| 图片懒加载 + 骨架屏 | 对于电商/Feed流页面效果更好 |
| CDN + 懒加载 | 进一步减少图片加载延迟 |
七、懒加载的局限性
- 影响 SEO(搜索引擎可能抓不到延迟加载的图片)
- 对首屏图片不应使用懒加载(会增加白屏时间)
- 对滚动过快的情况,可能出现闪烁(指图片进入视图才发请求,会出现空白或模糊图到清晰图的情况,故需提前预加载)
八、总结
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
IntersectionObserver | 监听元素进入视口 | 性能好、实现简单 | 兼容性略差 |
scroll + 计算位置 | 手动监听滚动 | 兼容好 | 需节流优化 |
<img loading="lazy"> | 浏览器原生支持 | 最简单 | 兼容性需检测 |
最推荐方案:优先使用 <img loading="lazy">, 若需兼容旧浏览器,则采用 IntersectionObserver 作为兜底方案。
九、面试速记模板
图片懒加载是指页面初始只加载首屏需要的图片,其余图片等进入视口再加载,降低首屏加载时间和资源消耗。
实现方法:先给图片占位或空 src,真实地址存 data-src;当图片进入或快要进入视口时,将 data-src 赋值给 src。
三种常用方式:
IntersectionObserver监听可视区scroll事件计算位置手动加载(需防抖/节流)- 浏览器原生属性
loading="lazy"
⚠️ 首屏图片不宜懒加载,滚动长列表、图集适用。