“打开网页半天没反应?”、“滚动时卡顿严重?”——如果你的网站充斥着大量高清图片,尤其是电商、资讯类站点,这些“视觉盛宴”背后往往藏着性能黑洞。
而图片懒加载(Lazy Load),正是解决这一问题的利器。它能让你的网页加载速度提升 50% 以上,同时减少服务器压力和用户流量消耗。
本文将带你从零开始,深入理解懒加载的核心原理,手把手实现基础版与进阶版代码,并对比不同方案的优缺点,助你在项目中灵活应用!
🔍 一、什么是懒加载?为什么需要它?
1.1 什么是懒加载?
懒加载(Lazy Load),也叫延迟加载,是一种前端优化策略。其核心思想是:
只加载当前可视区域内的资源,其余资源在用户滚动到它们附近时再加载。
尤其适用于图片密集型页面,如电商首页、社交动态流、新闻列表等。
1.2 为什么要使用懒加载?
✅ 提升首屏加载速度
- 页面首屏只需加载可视区图片,避免一次性下载所有图片。
- 数据显示:页面加载每延迟 0.5 秒,跳出率上升 20%。
✅ 减少无效请求
- 用户可能根本不会滚动到底部,提前加载只会浪费带宽和服务器资源。
✅ 降低并发压力
- 浏览器默认并发请求数有限,过多图片会阻塞 CSS/JS 加载,导致白屏或交互延迟。
🧠 二、懒加载的核心原理
2.1 实现思路
-
占位图 + 自定义属性
- 将真实图片地址存储在
data-src中; src设置为小尺寸占位图(如 loading.gif 或透明 1x1 图片)。
- 将真实图片地址存储在
-
监听滚动事件 / IntersectionObserver
- 判断图片是否进入可视区域;
- 若进入,则将
src替换为data-src的值,触发加载。
-
优化体验细节
- 使用节流函数控制滚动频率;
- 预加载即将进入视口的图片;
- 失败处理、缓存机制等。
2.2 关键知识点回顾
| 技术点 | 描述 |
|---|---|
data-* 属性 | 存储自定义数据,用于保存真实图片地址 |
getBoundingClientRect() | 获取元素相对于视口的位置 |
window.addEventListener('scroll') | 监听滚动事件判断图片是否可见 |
Image() 构造函数 | 创建临时图片对象预加载资源 |
IntersectionObserver API | 现代浏览器推荐使用的异步监听方式 |
🛠️ 三、从零实现一个懒加载功能
3.1 HTML 结构
<img class="lazy" src="loading.gif" data-src="aw.jpg" />
<img class="lazy" src="loading.gif" data-src="aw.jpg" />
<!-- 更多图片... -->
3.2 JavaScript 实现(基础版)
function lazyload() {
const images = document.querySelectorAll('img[data-src]');
const viewHeight = window.innerHeight;
images.forEach(img => {
if (img.dataset.src === '') return;
const rect = img.getBoundingClientRect();
if (rect.top < viewHeight && rect.bottom > 0) {
const realSrc = img.dataset.src;
const tempImg = new Image();
tempImg.onload = () => {
img.src = realSrc;
img.removeAttribute('data-src');
};
tempImg.src = realSrc;
}
});
}
// 初始化加载 + 滚动监听
window.addEventListener('DOMContentLoaded', lazyload);
window.addEventListener('scroll', lazyload);
3.3 性能优化建议
- ✅ 使用节流函数减少频繁调用:
function throttle(fn, delay) {
let timer = null;
return function () {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
}
};
}
window.addEventListener('scroll', throttle(lazyload, 100));
- ✅ 使用
IntersectionObserver替代 scroll 监听:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img); // 可选:加载完停止观察
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));
⚙️ 四、进阶技巧与注意事项
4.1 占位图设计
- 推荐使用固定大小的占位图,防止布局抖动;
- 可使用 Base64 编码的小图内联减少 HTTP 请求。
如果不懂Base64,可以看看这篇文章前端高手才知道的秘密:Blob 居然这么强大!你是否想过,网页中那些炫酷的图片、文件下载、本地预览功能背后,隐藏着怎样的 - 掘金
4.2 预加载“未来”图片
通过 rootMargin 提前加载即将进入视口的图片:
new IntersectionObserver(callback, {
rootMargin: '0px 0px 200px 0px' // 距离底部 200px 就开始加载
});
4.3 错误处理
tempImg.onerror = () => {
img.src = 'default.png'; // 加载失败备用图
};
4.4 兼容性处理
- IE 不支持
IntersectionObserver,可使用 polyfill 或回退到 scroll + getBoundingClientRect 方案。
📊 五、懒加载 vs 预加载:谁更适合你?
| 对比维度 | 懒加载(Lazy Load) | 预加载(Preload) |
|---|---|---|
| 适用场景 | 图片多、页面长、非关键路径资源 | 首屏关键资源、动画序列图 |
| 加载时机 | 滚动到可视区后加载 | 页面加载前就预加载 |
| 优点 | 首屏快、节省流量、减轻服务器压力 | 后续操作流畅无等待 |
| 缺点 | 需要监听和判断逻辑,用户体验略差 | 初次加载慢,占用更多带宽 |
📌 六、总结
图片懒加载是一项简单但效果显著的前端性能优化手段。掌握它的原理和实现方式,不仅能提升用户体验,还能减少服务器压力,在电商、社区、新闻等高并发场景中尤为重要。
✅ 本文重点回顾:
- 懒加载本质是“按需加载”,避免一次性加载所有图片;
- 使用
data-src和src分离真实地址与占位图; - 基础实现依赖滚动监听 +
getBoundingClientRect(); - 进阶方案使用
IntersectionObserver,更高效且兼容现代浏览器; - 注意节流、错误处理、预加载等优化技巧。