1、主要使用IntersectionObserver API
自定义useIntersectionObserver Hook
import { useEffect, useRef, useState } from 'react';
const useIntersectionObserver = (callback, options) => {
const [entry, setEntry] = useState(null);
const observer = useRef(null);
useEffect(() => {
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver(([entry],_observer) => {
setEntry(entry);
if (entry.isIntersecting) { // 一个布尔值,表示目标元素是否与根元素有交集。
callback(entry); // 设置src加载图片,将观察对象回传callback
_observer.unobserve(entry.target); // 一旦图片加载完成,可以停止观察该元素
}
}, options);
return () => {
if (observer.current) observer.current.disconnect();
};
}, [callback, options]);
return { setTarget: (node) => node && observer.current.observe(node) };
};
创建 LazyImage 组件
import React, { useRef, useState } from 'react';
const LazyImage = ({ src, alt, placeholder }) => {
const [isLoaded, setIsLoaded] = useState(false);
const imgRef = useRef();
const onIntersect = () => {
if (imgRef.current) {
imgRef.current.src = src;
imgRef.current.onload = () => setIsLoaded(true);
}
};
const { setTarget } = useIntersectionObserver(onIntersect, {
root: null, // 使用视口作为根元素
rootMargin: '0px',
threshold: 0.1, // 当至少 10% 的目标元素进入视口时触发回调
});
return (
<div ref={setTarget} style={{ minHeight: '200px', minWidth: '200px' }}>
<img
ref={imgRef}
src={isLoaded ? src : placeholder}
alt={alt}
style={{ opacity: isLoaded ? 1 : 0.5, transition: 'opacity 0.5s' }}
/>
</div>
);
};
export default LazyImage;
使用 LazyImage 组件
import React from 'react';
import LazyImage from './LazyImage';
const App = () => {
return (
<div>
<h1>Lazy Load Images Example</h1>
<LazyImage
src="https://example.com/image.jpg"
alt="Example Image"
placeholder="https://via.placeholder.com/200"
/>
{/* 可以添加更多的 LazyImage 组件 */}
</div>
);
};
export default App;
Top comments (0)