在网页性能优化的版图中,图片懒加载是不可或缺的一块拼图。它通过延迟加载非可视区域的图片,减少页面初始加载的资源体积,从而加快首屏渲染速度、降低服务器压力。从早期的手动实现方案,到如今HTML原生提供的loading属性,图片懒加载的实现方式经历了多次迭代。本文将带你深入了解这两种方案的原理、实现方式及适用场景。
🛠️ 传统手动懒加载:原生JS实现思路
手动实现图片懒加载的核心逻辑,是通过监听页面滚动事件,判断图片是否进入视口,若进入则将data-src(或自定义属性)中的真实图片地址赋值给src属性,触发图片加载。
实现步骤
- HTML结构改造 将图片的真实地址存储在
data-src属性中,src属性可设置为一张占位图(如1×1的透明像素),避免页面出现错误图标:Html复制<img class="lazy" data-src="https://example.com/image1.jpg" src="placeholder.png" alt="示例图片">
<img class="lazy" data-src="https://example.com/image2.jpg" src="placeholder.png" alt="示例图片"> - JavaScript核心逻辑
- 监听
scroll事件,或使用性能更优的IntersectionObserverAPI - 对每个懒加载图片进行可见性判断
- 当图片进入视口时,替换
src属性并移除监听
基于
IntersectionObserver的实现代码:Javascript复制document.addEventListener('DOMContentLoaded', function() {
const lazyImages = document.querySelectorAll('img.lazy');const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});lazyImages.forEach(img => {
observer.observe(img);
});
}); - 监听
- CSS优化体验 为图片添加过渡动画,提升加载过程的视觉体验:
Css复制
img.lazy {
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
img.lazy.loaded {
opacity: 1;
}在JS中图片加载完成后,为图片添加
loaded类名即可触发动画。
方案优缺点
- 优点:兼容性好,可适配所有现代浏览器;高度自定义,可根据需求扩展功能(如加载错误重试、预加载距离调整等)
- 缺点:需要编写额外的JS和CSS代码;
scroll事件监听存在性能隐患(需节流处理);实现复杂,容易出现边缘情况(如页面缩放、动态添加图片等)
⚡ HTML原生懒加载:loading属性的便捷之道
为了简化图片懒加载的实现,HTML5.2标准引入了loading属性,开发者无需编写任何JavaScript代码,只需为img标签添加该属性即可实现懒加载。
基本用法
loading属性支持三个值:
lazy:启用懒加载,图片将在进入视口附近时才开始加载eager:立即加载图片,无论其是否在视口内(默认行为)auto:由浏览器决定是否启用懒加载
<img src="https://example.com/image1.jpg" loading="lazy" alt="示例图片">
<img src="https://example.com/image2.jpg" loading="lazy" alt="示例图片">浏览器兼容性
截至2026年,loading属性已得到绝大多数现代浏览器的支持:
- Chrome/Edge:77+
- Firefox:75+
- Safari:15.4+
- 移动端浏览器:Android WebView 77+、iOS Safari 15.4+
对于不支持该属性的浏览器,图片会默认采用立即加载的方式,不会影响页面功能。
方案优缺点
- 优点:实现成本极低,只需添加一个属性;性能更优,浏览器原生实现的懒加载比JS实现更高效;无需维护额外的代码
- 缺点:兼容性存在一定限制(不支持IE及旧版本浏览器);自定义程度低,无法灵活调整加载阈值、加载动画等细节
📊 两种方案的对比与选型建议
| 对比维度 | 手动JS实现方案 | 原生loading属性方案 |
|---|---|---|
| 实现成本 | 高(需编写JS/CSS代码) | 极低(仅需添加属性) |
| 兼容性 | 好(支持所有现代浏览器) | 较好(不支持旧版浏览器) |
| 自定义程度 | 高(可灵活扩展功能) | 低(仅支持基础配置) |
| 性能表现 | 较好(需优化事件监听) | 优(浏览器原生优化) |
| 维护成本 | 高(需处理边缘情况) | 低(无需维护额外代码) |
选型建议
- 优先使用原生
loading属性:如果你不需要兼容旧版浏览器,且对懒加载的自定义需求不高,原生方案是最优选择,它能以最低的成本实现良好的性能优化效果。 - 手动方案作为补充:当需要兼容旧版浏览器,或需要实现更复杂的懒加载逻辑(如加载错误重试、自定义加载阈值等)时,手动JS方案仍是可靠的选择。
- 渐进式增强策略:可以结合两种方案,通过JS检测浏览器是否支持
loading属性,若不支持则加载手动懒加载的代码,实现渐进式增强:Javascript复制if ('loading' in HTMLImageElement.prototype) {
// 浏览器支持原生懒加载,无需额外处理
} else {
// 加载手动懒加载的JS代码
const script = document.createElement('script');
script.src = 'lazyload.js';
document.body.appendChild(script);
}
🎯 总结与展望
图片懒加载作为一项经典的性能优化技术,从手动实现到原生支持的发展历程,体现了Web标准对开发者需求的持续关注。原生loading属性的出现,极大降低了懒加载的实现成本,让更多开发者能够轻松应用这一优化方案。
未来,随着浏览器兼容性的不断提升,原生懒加载方案将逐渐成为主流。但在相当长的一段时间内,手动实现方案仍会在需要兼容旧版浏览器或自定义需求较高的场景中发挥作用。作为开发者,我们需要根据项目的实际需求,灵活选择合适的实现方案,在开发效率与性能优化之间找到最佳平衡。