React中如何等待所有图片加载完成后隐藏Loading组件?
React 图片批量加载优化方案
问题场景
我使用ReactJS开发页面,现有简化代码如下:
const Page = () => { const [isLoading, setIsLoading] = useState(true); return ( <Loading isLoading={isLoading} > <img src='https://example.com/img1' alt='image' /> <img src='https://example.com/img2' alt='image' /> <img src='https://example.com/img3' alt='image' /> <img src='https://example.com/img4' alt='image' /> <img src='https://example.com/img5' alt='image' /> <img src='https://example.com/img6' alt='image' /> <img src='https://example.com/img7' alt='image' /> </Loading> ) }
当前问题
图片会逐个渐进式显示,视觉效果差,加载过程中页面布局频繁跳动。
期望效果
页面打开时先展示<Loading>组件(isLoading设为true),待所有图片加载完成后,再将isLoading设为false,隐藏加载组件,一次性展示所有图片。
解决方案
通过预加载所有图片并监听加载状态,全部完成后切换isLoading状态,具体实现代码如下:
import { useState, useEffect } from 'react'; const Page = () => { const [isLoading, setIsLoading] = useState(true); // 统一管理图片地址数组 const imageUrls = [ 'https://example.com/img1', 'https://example.com/img2', 'https://example.com/img3', 'https://example.com/img4', 'https://example.com/img5', 'https://example.com/img6', 'https://example.com/img7' ]; useEffect(() => { let loadedCount = 0; const totalImages = imageUrls.length; // 遍历预加载所有图片 imageUrls.forEach(url => { const img = new Image(); img.src = url; // 图片加载成功回调 img.onload = () => { loadedCount++; checkAllLoaded(); }; // 图片加载失败也计入完成,避免加载状态卡死 img.onerror = () => { loadedCount++; checkAllLoaded(); }; }); // 检查是否所有图片已加载完成 const checkAllLoaded = () => { if (loadedCount === totalImages) { setIsLoading(false); } }; // 组件卸载时清理计数,避免状态更新报错 return () => { loadedCount = totalImages; }; }, [imageUrls]); return ( <Loading isLoading={isLoading} > {imageUrls.map((url, index) => ( <img key={index} src={url} alt={`image ${index + 1}`} /> ))} </Loading> ) }
方案说明
- 将图片地址存入数组,既方便预加载遍历,也能通过
map渲染图片元素,减少重复代码。 - 利用
useEffect在组件挂载时启动预加载,通过原生Image对象加载图片,同时监听成功和失败事件,确保所有图片状态都被统计。 - 每完成一张图片加载(无论成功失败)就计数,当计数等于图片总数时,切换加载状态,一次性展示所有内容。
- 添加清理函数,防止组件卸载后触发状态更新,避免内存泄漏。
内容的提问来源于stack exchange,提问作者arrmani88
相关产品推荐
相关产品推荐

