Введение
В этом практическом занятии мы изучим, как реализовать отложенную загрузку изображений в приложении на React. Отложенная загрузка улучшает производительность страницы, задерживая загрузку изображений до тех пор, пока они не понадобятся, сокращая время начальной загрузки и улучшая пользовательский опыт. Мы будем использовать API Intersection Observer и 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(), чтобы создать два ref. Один будет хранить элемент<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, чтобы улучшить свои навыки.