什么是懒加载?
懒加载是一种延迟加载策略,意味着资源或数据不会在应用初始化时就加载,而是只有在需要时才进行加载。在 Web 前端开发中,懒加载通常指的是在用户滚动或其他交互触发时才加载图像、模块、组件等资源。这样可以减少不必要的初始加载时间,提高页面渲染速度。
为什么需要懒加载?
- 性能优化:懒加载可以避免在页面加载时一次性加载所有资源,减小页面初次加载的体积。
- 带宽节省:用户可能并不会访问页面上的所有内容,通过懒加载可以减少无用资源的加载,节省带宽。
- 提升用户体验:让用户在最短的时间内看到页面的主要内容,其他资源可以在用户需要时再加载。
懒加载的常见实现方式
- 图片懒加载:图片懒加载是最常见的应用场景,只有当图片即将出现在视口时才会加载。
- 组件懒加载:在 SPA 中,可以通过路由懒加载或按需加载 Vue、React 等框架中的组件。
- 模块懒加载:通过动态
import()加载模块,减少初始加载的 JS 文件大小。
如何实现图片懒加载?
下面通过一个简单的图片懒加载示例来演示如何实现懒加载。
1. 基本原理
图片懒加载的原理是:默认情况下,图片的 src 属性不会直接指向真实的图片地址,而是指向一个占位图或空白图。图片的真实地址会设置在 data-src 或 data-lazy 等自定义属性上。当图片即将进入视口时,才会通过 JavaScript 设置图片的 src 属性,加载真实的图片。
2. HTML 结构
我们将使用 data-src 属性存储图片的真实地址,src 属性存储占位图地址,初始时显示一个小的占位符图片。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片懒加载</title>
<style>
.img-container {
width: 100%;
height: 300px;
margin: 20px 0;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
</head>
<body>
<div class="img-container">
<img data-src="image1.jpg" src="placeholder.jpg" alt="image1" class="lazy-load">
</div>
<div class="img-container">
<img data-src="image2.jpg" src="placeholder.jpg" alt="image2" class="lazy-load">
</div>
<div class="img-container">
<img data-src="image3.jpg" src="placeholder.jpg" alt="image3" class="lazy-load">
</div>
<script src="lazyload.js"></script>
</body>
</html>
3. JavaScript 实现
下面的 JavaScript 使用了原生 IntersectionObserver API 来判断图片是否进入视口,当图片即将出现在视口时,懒加载该图片。
// lazyload.js
document.addEventListener("DOMContentLoaded", function () {
// 创建 IntersectionObserver 实例
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
// 判断图片是否进入视口
if (entry.isIntersecting) {
const img = entry.target;
// 将 data-src 的真实图片地址赋值给 src 属性
img.src = img.getAttribute('data-src');
// 图片加载完成后,停止观察该图片
observer.unobserve(img);
}
});
}, {
// 设置视口的边距,提前加载
rootMargin: "50px 0px"
});
// 获取所有带有 lazy-load 类的图片
const images = document.querySelectorAll('.lazy-load');
// 开始观察每一张图片
images.forEach(img => {
observer.observe(img);
});
});
4. 代码解释
-
HTML 结构:
- 每张图片使用
data-src属性存储真实的图片地址,而src属性则指向一个占位图(如placeholder.jpg)。这样一开始图片是不可见的。 - 每个图片都带有一个
lazy-load类,方便我们在 JavaScript 中选择。
- 每张图片使用
-
JavaScript 代码:
IntersectionObserver用于监听图片是否进入视口。entries是一组IntersectionObserverEntry对象,代表了每一个被观察的元素的状态。- 在
entries中,我们判断entry.isIntersecting是否为true,即图片是否进入了视口。如果进入了视口,就加载图片。 - 通过
img.getAttribute('data-src')获取图片的真实地址,并赋值给src属性,这样浏览器就开始加载该图片。 - 一旦图片加载完毕,调用
observer.unobserve(img)停止观察该图片,以提高性能。
5. 代码优化
可以通过使用 requestIdleCallback 来优化懒加载的性能,或者利用第三方库(如 lazysizes)来增强懒加载功能,支持更复杂的场景和更好的兼容性。
如何实现组件懒加载?
在现代 JavaScript 框架(如 Vue 和 React)中,组件懒加载通常通过动态导入(import())来实现。下面展示在 Vue 和 React 中如何实现组件懒加载。
Vue 组件懒加载
在 Vue 中,懒加载组件非常简单,可以通过 Vue 的 defineAsyncComponent 实现:
<template>
<div>
<h1>欢迎来到 Vue 应用</h1>
<lazy-loaded-component />
</div>
</template>
<script>
import { defineAsyncComponent } from 'vue';
export default {
components: {
// 懒加载组件
'lazy-loaded-component': defineAsyncComponent(() =>
import('./LazyLoadedComponent.vue')
)
}
}
</script>
在上面的代码中,LazyLoadedComponent.vue 组件会被懒加载,只有在需要时才会被加载。
React 组件懒加载
在 React 中,可以使用 React.lazy 和 Suspense 来实现懒加载:
import React, { Suspense } from 'react';
// 使用 React.lazy 实现懒加载
const LazyLoadedComponent = React.lazy(() => import('./LazyLoadedComponent'));
function App() {
return (
<div>
<h1>欢迎来到 React 应用</h1>
<Suspense fallback={<div>加载中...</div>}>
<LazyLoadedComponent />
</Suspense>
</div>
);
}
export default App;
在上面的代码中,LazyLoadedComponent 会被懒加载,Suspense 组件用于显示加载中的占位符。