Expo 中使用 Ant Design UI 组件
- dependencies
package.json
...
"dependencies": {
"@ant-design/icons-react-native": "^2.3.2",
"@ant-design/react-native": "^5.1.0",
"@react-navigation/bottom-tabs": "^6.5.12",
"@react-navigation/native": "^6.1.10",
"@react-navigation/native-stack": "^6.9.18",
"@reduxjs/toolkit": "^2.2.1",
"babel-plugin-import": "^1.13.8",
"expo": "~50.0.7",
"expo-font": "~11.10.3",
"expo-status-bar": "~1.11.1",
"react": "18.2.0",
"react-native": "0.73.4",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-redux": "^9.1.0",
"expo-splash-screen": "~0.26.4"
},
...
假设你已经按照 expo 官方文档 docs.expo.dev/ 创建好了项目. 现在根据 Ant Design Mobile RN of React 官方文档 rn.mobile.ant.design/docs/react/… 快速上手.
我推荐使用 expo 或者 npx expo 代替 npm/yarn 去安装.
- 安装
npx expo install @ant-design/react-native
npx expo install @ant-design/icons-react-native
- 按需加载
npx expo install babel-plugin-import
修改 babel.confjg.js, 添加:
{
"plugins": [
["import", { libraryName: "@ant-design/react-native" }] // 与 Web 平台的区别是不需要设置 style
]
}
添加后, 你的 babel.config.js 应该是这样:
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
["import", { libraryName: "@ant-design/react-native" }], // 与 Web 平台的区别是不需要设置 style
],
};
};
接下来就与文档有点出入了, 因为官方文档使用的版本比较旧吧(仍然在使用 class component)
我们需要安装 expo-splash-screen, 因为~~# expo-app-loading~~已经 deprecated, 被 expo-splash-screen 所取代. 以及 expo-font
npx expo install expo-splash-screen
npx expo install expo-font
然后根据 expo-font 文档 docs.expo.dev/versions/la…
- 配置
app.json(实战中, 我发现不配置也没影响. 还是配置上吧, 跟着文档走)
当你运行完 npx expo install expo-font 的时候, 你的 app.json 应该是
app.json
{
"expo": {
...
"plugins": [
"expo-font"
]
}
}
修改完之后:
{
"expo": {
...
"plugins": [
[
"expo-font",
{
"fonts": [
"node_modules/@ant-design/icons-react-native/fonts/antoutline.ttf",
"node_modules/@ant-design/icons-react-native/fonts/antfill.ttf"
]
}
]
]
}
}
注意, plugin后面是两层括号 "plugins": [[...]]
- 修改 App.tsx (functional component)
import { useCallback } from "react";
import { NavigationContainer } from "@react-navigation/native";
import { useFonts } from "expo-font";
import * as SplashScreen from "expo-splash-screen";
// Keep the splash screen visible while we fetch resources
SplashScreen.preventAutoHideAsync();
export default function App() {
const [fontsLoaded, fontError] = useFonts({
antoutline: require("@ant-design/icons-react-native/fonts/antoutline.ttf"),
antfill: require("@ant-design/icons-react-native/fonts/antfill.ttf"),
});
const onLayoutRootView = useCallback(async () => {
if (fontsLoaded || fontError) {
await SplashScreen.hideAsync();
}
}, [fontsLoaded, fontError]);
if (!fontsLoaded && !fontError) {
return null;
}
return (
<>
<StatusBar style="auto" />
<NavigationContainer onReady={onLayoutRootView}>
<Stack.Navigator>
<Stack.Screen name="MainOverview" component={LoginScreen} />
</Stack.Navigator>
</NavigationContainer>
</>
);
}
注意一点, 官方试例中使用的是 View, onLayoutRootView 传递给 onLayout,
- View
<View style={styles.container} onLayout={onLayoutRootView}>
如果你使用的是 NavigationContainer, 你需要将 onLayoutRootView 传递给 onReady.
- NavigationContainer
<NavigationContainer onReady={onLayoutRootView}>
- 最后使用:
import { Button as AntButton, Icon } from "@ant-design/react-native/lib";
import React from "react";
import { StyleSheet, View } from "react-native";
const LoginScreen = () => {
return (
<View style={styles.container}>
<View>
<AntButton>
<Icon name="alert" color="red" />
</AntButton>
</View>
</View>
);
};
export default LoginScreen;
const styles = StyleSheet.create({
container: {
width: "auto",
flex: 1,
backgroundColor: "white",
alignItems: "center",
},
});
- 效果图:
最后的彩蛋, 参考 那其实不用搞这些乱七八糟的, 你不用安装 @ant-design/icons-react-native, 你可以使用 expo 内置的@expo/vector-icons里面的 AntDesign icons(不过里面的 icon 并没有 Ant Design 那么丰富, 比如 示例中的alert 就没有.
- 下面从
@expo/vector-icons添加一个user试试
import { AntDesign } from '@expo/vector-icons';