懒加载(Lazy Loading) 是一种优化网页性能的技术,主要用于延迟加载非关键资源(如图片、视频、脚本等),直到它们真正需要被使用时才加载。懒加载可以显著减少页面初始加载时间,降低带宽消耗,并提升用户体验。
1. 懒加载的核心思想
懒加载的核心思想是 按需加载。具体来说:
- 初始加载:只加载当前视口(Viewport)内的资源,或者只加载用户可见的内容。
- 延迟加载:当用户滚动页面或资源进入视口时,再动态加载这些资源。
2. 懒加载的应用场景
- 图片懒加载:延迟加载页面中的图片,直到图片进入视口。
- 视频懒加载:延迟加载视频资源,直到用户点击播放按钮。
- 脚本懒加载:延迟加载非关键脚本,直到页面主要内容加载完成。
- 分页加载:在长列表或分页内容中,只加载当前可见的部分,滚动时再加载更多内容。
3. 图片懒加载的实现
图片懒加载是最常见的懒加载场景。以下是两种实现方式:
方法 1:使用 IntersectionObserver
API(推荐)
IntersectionObserver
是浏览器提供的一个 API,用于监听目标元素是否进入视口。
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lazy Loading Images</title>
<style>
img {
width: 100%;
height: 300px;
background: #eee;
display: block;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div>
<img data-src="https://picsum.photos/800/600?random=1" alt="Image 1">
<img data-src="https://picsum.photos/800/600?random=2" alt="Image 2">
<img data-src="https://picsum.photos/800/600?random=3" alt="Image 3">
<img data-src="https://picsum.photos/800/600?random=4" alt="Image 4">
<img data-src="https://picsum.photos/800/600?random=5" alt="Image 5">
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
const images = document.querySelectorAll("img[data-src]");
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.getAttribute("data-src");
img.removeAttribute("data-src");
observer.unobserve(img); // 停止观察已加载的图片
}
});
}, {
rootMargin: "0px",
threshold: 0.1 // 当图片进入视口 10% 时触发加载
});
images.forEach(img => {
observer.observe(img); // 开始观察每个图片
});
});
</script>
</body>
</html>
代码解析
data-src
属性:将图片的真实 URL 存储在data-src
属性中,而不是直接放在src
属性里。IntersectionObserver
:- 监听每个图片是否进入视口。
- 当图片进入视口时,将
data-src
的值赋给src
属性,触发图片加载。 - 加载完成后,停止观察该图片。
- 性能优化:通过
rootMargin
和threshold
参数,可以控制图片进入视口的触发条件。
方法 2:使用滚动事件监听(传统方法)
在没有 IntersectionObserver
的情况下,可以通过监听滚动事件来实现懒加载。
代码实现
function lazyLoadImages() {
const images = document.querySelectorAll("img[data-src]");
images.forEach(img => {
const rect = img.getBoundingClientRect();
if (rect.top < window.innerHeight && rect.bottom >= 0) {
img.src = img.getAttribute("data-src");
img.removeAttribute("data-src");
}
});
}
window.addEventListener("load", lazyLoadImages);
window.addEventListener("scroll", lazyLoadImages);
window.addEventListener("resize", lazyLoadImages);
代码解析
getBoundingClientRect()
:获取图片相对于视口的位置。- 判断条件:如果图片的顶部进入视口(
rect.top < window.innerHeight
),则加载图片。 - 事件监听:在页面加载、滚动和窗口大小变化时触发懒加载。
4. 懒加载的优化
1. 占位符(Placeholder)
在图片加载之前,可以使用一个占位符(如纯色背景或低分辨率图片)来避免页面布局抖动。
<img data-src="image.jpg" src="placeholder.jpg" alt="Image">
2. 预加载
对于即将进入视口的图片,可以提前加载,避免用户滚动时出现空白。
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.getAttribute("data-src");
img.removeAttribute("data-src");
observer.unobserve(img);
}
});
}, {
rootMargin: "200px 0px", // 提前 200px 加载
threshold: 0.1
});
3. 图片加载失败处理
如果图片加载失败,可以显示一个默认图片。
img.onerror = function() {
this.src = "default.jpg";
};
5. 懒加载的优缺点
优点
- 减少初始加载时间:只加载用户可见的内容,提升页面加载速度。
- 节省带宽:减少不必要的资源加载,降低服务器压力。
- 提升用户体验:避免页面卡顿,提供更流畅的交互体验。
缺点
- 实现复杂度:需要额外的代码逻辑来实现懒加载。
- SEO 影响:如果搜索引擎爬虫无法正确解析懒加载的内容,可能会影响 SEO。
6. 总结
懒加载是一种非常实用的性能优化技术,特别适用于包含大量图片或长列表的页面。通过 IntersectionObserver
或滚动事件监听,可以轻松实现懒加载功能。结合占位符、预加载和错误处理,可以进一步提升用户体验。
在实际项目中,可以根据需求选择合适的懒加载方案,并结合其他优化技术(如防抖、节流)来达到最佳性能。