React中如何监听字体加载事件并实现state状态更新?
React 监听字体加载完成的实现方案
你可以直接使用浏览器原生的 Font Loading API 实现需求,该API在所有现代浏览器中都有良好支持,不需要额外引入第三方依赖。
场景1:提前在CSS中定义好的固定字体
首先你需要先在CSS中通过@font-face声明字体:
@font-face { font-family: 'CustomFont'; src: url('./fonts/CustomFont.woff2') format('woff2'); font-weight: normal; font-style: normal; }
之后在React组件中通过document.fonts.load监听加载状态,示例代码如下:
import { useState, useEffect } from 'react'; function App() { const [isFontLoaded, setIsFontLoaded] = useState(false); useEffect(() => { const checkFontLoad = async () => { try { // 参数格式为 字号 字体名,字号可任意填写合法值 await document.fonts.load('16px CustomFont'); setIsFontLoaded(true); } catch (error) { console.error('字体加载失败', error); // 可在此处添加降级逻辑,比如直接设置为系统默认字体 } }; checkFontLoad(); }, []); return ( <div style={{ fontFamily: isFontLoaded ? 'CustomFont' : 'sans-serif' }}> {isFontLoaded ? '字体已加载完成' : '加载中...'} </div> ); } export default App;
场景2:运行时动态引入的字体
如果字体路径是动态获取的,没有提前在CSS中声明,可以通过FontFace接口手动创建字体实例加载:
import { useState, useEffect } from 'react'; function DynamicFontPage({ fontUrl, fontName }) { const [isFontLoaded, setIsFontLoaded] = useState(false); useEffect(() => { if (!fontUrl || !fontName) return; const loadDynamicFont = async () => { try { const customFont = new FontFace(fontName, `url(${fontUrl})`); // 触发字体加载 const loadedFont = await customFont.load(); // 将加载完成的字体加入文档字体集合 document.fonts.add(loadedFont); setIsFontLoaded(true); } catch (error) { console.error('动态字体加载失败', error); } }; loadDynamicFont(); }, [fontUrl, fontName]); return ( <div style={{ fontFamily: isFontLoaded ? fontName : 'sans-serif' }}> 动态字体测试内容 </div> ); } export default DynamicFontPage;
注意事项
- 如果需要监听页面中所有声明的字体全部加载完成,可以直接等待
document.fonts.ready这个Promise resolve即可,不需要单独指定每个字体。 - 加载失败的回调中可以添加字体降级逻辑,避免页面出现布局偏移或者内容空白。
- 如需兼容不支持Font Loading API的旧浏览器,可以引入对应的polyfill实现相同效果。
内容的提问来源于stack exchange,提问作者Zagaek98y
相关产品推荐
相关产品推荐

