简介
在本实验中,我们将探索如何在 React 应用程序中实现图片懒加载。懒加载通过延迟图片加载直到需要时才进行,从而提高页面性能,减少初始加载时间并改善用户体验。我们将使用 Intersection Observer API 和 React 钩子来创建一个支持懒加载图片的可复用组件。
图片懒加载
虚拟机中已提供
index.html和script.js。一般来说,你只需在script.js和style.css中添加代码。
要渲染支持懒加载的图片,请按以下步骤操作:
- 使用
useState()钩子创建一个有状态的值,用于指示图片是否已加载。 - 使用
useEffect()钩子检查HTMLImageElement.prototype是否包含'loading'。这将检查是否原生支持懒加载。如果不支持,则创建一个新的IntersectionObserver,并使用IntersectionObserver.observer()来观察<img>元素。使用钩子的返回值在组件卸载时进行清理。 - 使用
useCallback()钩子来记忆IntersectionObserver的回调函数。此回调将更新isLoaded状态变量,并使用IntersectionObserver.disconnect()断开IntersectionObserver实例的连接。 - 使用
useRef()钩子创建两个引用。一个将保存<img>元素,另一个在必要时保存IntersectionObserver实例。 - 最后,使用给定的属性渲染
<img>元素。如有必要,应用loading='lazy'使其懒加载。使用isLoaded来确定src属性的值。
以下是这些步骤的示例实现:
const LazyLoadImage = ({
alt,
src,
className,
loadInitially = false,
observerOptions = { root: null, rootMargin: "200px 0px" },
...props
}) => {
const observerRef = React.useRef(null);
const imgRef = React.useRef(null);
const [isLoaded, setIsLoaded] = React.useState(loadInitially);
const observerCallback = React.useCallback(
(entries) => {
if (entries[0].isIntersecting) {
observerRef.current.disconnect();
setIsLoaded(true);
}
},
[observerRef]
);
React.useEffect(() => {
if (loadInitially) return;
if ("loading" in HTMLImageElement.prototype) {
setIsLoaded(true);
return;
}
observerRef.current = new IntersectionObserver(
observerCallback,
observerOptions
);
observerRef.current.observe(imgRef.current);
return () => {
observerRef.current.disconnect();
};
}, []);
return (
<img
alt={alt}
src={isLoaded ? src : ""}
ref={imgRef}
className={className}
loading={loadInitially ? undefined : "lazy"}
{...props}
/>
);
};
要使用此 LazyLoadImage 组件,只需使用图片的 src 和 alt 属性调用它:
ReactDOM.createRoot(document.getElementById("root")).render(
<LazyLoadImage
src="https://picsum.photos/id/1080/600/600"
alt="Strawberries"
/>
);
请点击右下角的“Go Live”在端口 8080 上运行网络服务。然后,你可以刷新“Web 8080”标签页来预览网页。
总结
恭喜你!你已经完成了图片懒加载实验。你可以在 LabEx 中练习更多实验来提升你的技能。