Expo 中使用 Ant Design Mobile RN of React

916 阅读2分钟

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 去安装.

image.png

  • 安装
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",
  },
});
  • 效果图:

antD_icon.gif

最后的彩蛋, 参考 那其实不用搞这些乱七八糟的, 你不用安装 @ant-design/icons-react-native, 你可以使用 expo 内置的@expo/vector-icons里面的 AntDesign icons(不过里面的 icon 并没有 Ant Design 那么丰富, 比如 示例中的alert 就没有.

image.png

  • 下面从 @expo/vector-icons 添加一个 user试试

image.png

import { AntDesign } from '@expo/vector-icons'; 

image.png

image.png