如何在Expo项目全局加载字体并实现字体加载代码复用?
在Expo项目中全局复用字体加载逻辑的方案
当然有办法解决这个重复造轮子的问题!在每个组件里写一遍字体加载代码确实既低效又容易让代码结构混乱,下面我会分享几种实用的全局复用方案,帮你在整个Expo项目里轻松搞定自定义字体的加载。
方案1:封装全局字体加载Hook + 根组件统一初始化
这种方案适合用Function组件的项目,核心思路是把字体加载逻辑封装成可复用的自定义Hook,然后在根组件里调用一次,让所有字体全局可用,子组件无需重复加载。
步骤1:创建自定义字体Hook
新建一个hooks/useLoadFonts.js文件,把所有需要的字体配置集中在这里:
import { useFonts } from 'expo-font'; export default function useLoadFonts() { const [fontsLoaded] = useFonts({ Montserrat: require('../assets/fonts/Montserrat.ttf'), 'Montserrat-SemiBold': require('../assets/fonts/Montserrat-SemiBold.ttf'), // 在这里添加所有你需要的自定义字体 }); return fontsLoaded; }
步骤2:在根组件中使用这个Hook
在根组件(比如App.js)里调用Hook,处理加载状态,字体加载完成后再渲染主应用:
import * as React from 'react'; import { View, ActivityIndicator, StyleSheet, Text } from 'react-native'; import useLoadFonts from './hooks/useLoadFonts'; // 导入你的主应用导航/页面组件 import MainApp from './MainApp'; export default function App() { const fontsLoaded = useLoadFonts(); // 字体未加载完成时,展示加载指示器(比返回null的空白体验更好) if (!fontsLoaded) { return ( <View style={styles.loadingContainer}> <ActivityIndicator size="large" color="#0000ff" /> <Text style={{ marginTop: 16 }}>加载字体中...</Text> </View> ); } // 字体加载完成后,渲染主应用 return <MainApp />; } const styles = StyleSheet.create({ loadingContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', }, });
之后所有子组件都可以直接使用这些字体,无需额外加载:
<Text style={{ fontFamily: 'Montserrat', fontSize: 24 }}>直接用全局加载的字体</Text>
方案2:基于Class组件的全局封装(兼容旧代码)
如果项目里还有Class组件的代码,可以用类似的思路封装一个全局加载逻辑,在根Class组件中统一处理:
步骤1:创建字体加载工具函数
新建utils/loadFonts.js:
import * as Font from 'expo-font'; export async function loadAppFonts() { await Font.loadAsync({ Montserrat: require('../assets/fonts/Montserrat.ttf'), 'Montserrat-SemiBold': { uri: require('../assets/fonts/Montserrat-SemiBold.ttf'), display: Font.FontDisplay.FALLBACK, }, // 其他需要的字体... }); }
步骤2:在根Class组件中调用
import * as React from 'react'; import { View, ActivityIndicator, StyleSheet, Text } from 'react-native'; import { loadAppFonts } from './utils/loadFonts'; import MainApp from './MainApp'; export default class App extends React.Component { state = { fontsLoaded: false, loadError: false, }; async componentDidMount() { try { await loadAppFonts(); this.setState({ fontsLoaded: true }); } catch (error) { console.error('字体加载失败:', error); this.setState({ loadError: true }); } } render() { const { fontsLoaded, loadError } = this.state; if (loadError) { return ( <View style={styles.errorContainer}> <Text>字体加载失败,请检查字体文件路径</Text> </View> ); } if (!fontsLoaded) { return ( <View style={styles.loadingContainer}> <ActivityIndicator size="large" color="#0000ff" /> </View> ); } return <MainApp />; } } const styles = StyleSheet.create({ loadingContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', }, errorContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 20, }, });
额外优化:自定义全局字体样式
为了进一步减少重复代码,你可以在styles/globalStyles.js中定义常用的字体样式,直接在组件中复用:
import { StyleSheet } from 'react-native'; export const globalStyles = StyleSheet.create({ montserratText: { fontFamily: 'Montserrat', }, montserratSemiBoldText: { fontFamily: 'Montserrat-SemiBold', }, headingText: { fontFamily: 'Montserrat-SemiBold', fontSize: 28, color: '#333', }, bodyText: { fontFamily: 'Montserrat', fontSize: 16, color: '#666', }, });
在组件中使用:
import { globalStyles } from './styles/globalStyles'; <Text style={globalStyles.headingText}>全局样式的标题</Text> <Text style={globalStyles.bodyText}>全局样式的正文</Text>
这样一来,你不仅实现了字体的全局加载,还能统一管理字体样式,让代码更整洁!
内容的提问来源于stack exchange,提问作者Thiago Henrique Santos
相关产品推荐
相关产品推荐

