React中如何实现图片懒加载?应在哪个文件层实现该功能?
首先回答你的第一个疑问:是的,常规的图片懒加载逻辑就是只有当图片进入(也可配置提前量,比如距离可视区还有200px时就触发)浏览器的可视区域时,才会发起资源请求,能大幅降低首屏的请求量和加载耗时。不过你现在的代码写法有个坑:你在SportImages.js里提前import了所有图片,这种写法会让构建工具把所有这些图片都标记为首屏依赖,就算你加了懒加载逻辑,这些图片还是会在首屏就全部加载,完全达不到懒加载的效果,这点要先修正。
懒加载逻辑的处理位置建议
不要在统一图片管理文件处理,也不要在每个业务组件重复写,最优方案是封装成通用的懒加载图片组件,理由如下:
- 图片管理文件只负责维护资源映射关系,和视图渲染逻辑解耦,后续改资源路径只需要改这一个文件
- 通用组件一次封装全项目复用,后续要加占位图、加载失败兜底、加载动画等功能,只需要改组件代码,不需要挨个改业务逻辑
调整步骤
- 先修正图片导入逻辑,避免全量提前加载:
如果你用的是CRA/Vite等标准React构建工具,把图片放到public/images目录下,修改SportImages.js为直接存路径即可:
// SportImages.js file export default { Football: '/images/football.png', Cricket: '/images/cricket.png', Soccer: '/images/soccer.png', // 剩余图片同理 }
如果不想把图片放到public目录,需要存在src文件夹下的话,删掉所有提前import的语句,配合动态导入使用即可。
- 两种懒加载实现方案可选:
方案1:原生属性实现(最简单,兼容95%以上现代浏览器)
直接给img标签加原生loading="lazy"属性即可,不需要额外逻辑:
cards.map(x => { return ( <img src={SportImages[x.image_ref]} loading="lazy" alt={x.name /* 建议补充alt属性优化无障碍体验 */} /> ) })
方案2:IntersectionObserver自定义实现(兼容性更强,可自定义配置)
封装通用懒加载图片组件,自定义预加载距离、加载状态等:
import { useState, useEffect, useRef } from 'react' const LazyImg = ({ src, alt, ...rest }) => { const [isLoaded, setIsLoaded] = useState(false) const imgRef = useRef(null) useEffect(() => { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { // 进入可视区后触发加载 const img = new Image() img.src = src img.onload = () => { setIsLoaded(true) observer.unobserve(imgRef.current) } } }) }, { rootMargin: '200px 0px' }) // 提前200px预加载,避免滑动到位置才加载出现空白 if (imgRef.current) observer.observe(imgRef.current) return () => observer.disconnect() }, [src]) return ( <div ref={imgRef} {...rest}> {isLoaded ? <img src={src} alt={alt} /> : <div className="img-placeholder" />} </div> ) } // 业务组件内直接调用 cards.map(x => { return <LazyImg src={SportImages[x.image_ref]} alt={x.name} /> })
内容的提问来源于stack exchange,提问作者willmahoney
相关产品推荐
相关产品推荐

