React+Material UI项目Google Fonts字体列表加载缓慢问题咨询
问题根因定位
你遇到的加载慢问题通常来自两个维度:
- 网络层面:Google Fonts公共接口响应慢、返回包体积大,加上带宽限制会拉长请求耗时
- 渲染层面:Google Fonts全量列表有1000+字体,默认全量渲染MenuItem会导致DOM节点过多,展开Select时触发大量重绘造成卡顿
可行解决方案
方案1:LocalStorage缓存字体列表(实现首次加载后秒开)
在原请求逻辑中增加缓存判断,同时可设置7天过期时间避免长期不更新字体库,修改后的useEffect代码如下:
const [googleFonts, setGoogleFonts] = useState(); useEffect(() => { let isMounted = true; let cancelToken = axios.CancelToken.source(); const fetchData = async () => { // 先查本地缓存 const cachedFonts = localStorage.getItem('googleFontsList'); const cacheExpire = localStorage.getItem('googleFontsExpire'); if (cachedFonts && cacheExpire && Date.now() < Number(cacheExpire)) { setGoogleFonts(JSON.parse(cachedFonts)); return; } try { let res = await client.get(); if (isMounted) { const fontList = res.data.items; setGoogleFonts(fontList); // 写入缓存,过期时间设为7天 localStorage.setItem('googleFontsList', JSON.stringify(fontList)); localStorage.setItem('googleFontsExpire', String(Date.now() + 7 * 24 * 60 * 60 * 1000)); } } catch (e) { console.error(e); // 请求失败降级用缓存 if (cachedFonts) setGoogleFonts(JSON.parse(cachedFonts)); }; } fetchData(); return () => { isMounted = false; cancelToken.cancel(); } }, []);
同时注意原列表渲染的key不要用index,替换为唯一的字体family值,避免渲染异常:
{googleFonts?.map((option) => ( <MenuItem key={option.family} value={option.family} > {option.family} </MenuItem> ))}
方案2:虚拟列表优化渲染性能
如果网络请求耗时低但展开Select仍卡顿,说明是全量渲染DOM导致的,使用虚拟滚动仅渲染可视区域的10-20个选项,可完全消除渲染延迟。你可以配合虚拟滚动库修改Select的下拉渲染逻辑,不用改动数据层代码。
方案3:本地静态字体列表(零网络请求)
如果不需要实时同步Google最新上线的字体,可以直接把Google Fonts的全量family列表导出为静态JSON文件存入项目源码,直接import使用,完全消除网络请求耗时,适合小型项目使用。
内容的提问来源于stack exchange,提问作者Asker
相关产品推荐
相关产品推荐

