react-intersection-observer
import React from 'react';
import { useInView } from 'react-intersection-observer';
const ImageLazyLoad = ({ src, alt }) => {
const { ref, inView } = useInView({ threshold: 0.1 });
return (
<img
ref={ref}
src={inView ? src : ''}
alt={alt}
style={{ opacity: inView ? 1 : 0 }}
/>
);
};
export default ImageLazyLoad;
直接使用 Intersection Observer API
import React, { useState, useEffect } from 'react';
const ImageLazyLoad = ({ src, alt }) => {
const [isLoaded, setIsLoaded] = useState(false);
const [imgRef, setImgRef] = useState(null);
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
setIsLoaded(true);
observer.unobserve(imgRef);
}
});
if (imgRef) {
observer.observe(imgRef);
}
return () => {
if (imgRef) {
observer.unobserve(imgRef);
}
};
}, [imgRef]);
return (
<img
ref={setImgRef}
src={isLoaded ? src : ''}
alt={alt}
style={{ opacity: isLoaded ? 1 : 0 }}
/>
);
};
export default ImageLazyLoad;
Next.js 里面的 Image 组件
import Image from 'next/image'
export default function Page() {
return (
<div className="grid-element">
<Image
priority // 设置为 ture 就是懒加载
fill
src="/example.png"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
)
}
本质实现的原理也是一样的,利用 Intersection Observer API
我想一些知名的开源组件也会这样优化 Image 组件。