引言
什么是 RN
RN 是 React Native 的简称, 它允许我们通过 react 的语法, 开发移动端 APP.
可以前往如下网址查看详细内容, 在这里仅作笔记记录, 可能不是很全.

APP 开发模式
移动端 APP 的开发模式有原生开发, 以及混合开发. 原生就是类似于 Android 就使用 Java / Kotlin, IPhone 就使用 Swift. 混合开发则指的是一次开发, 多端部署, RN 就是其中的一个. 另外的就是 H 5 开发, 其实就是普通的网页应用.
RN 就是本文所讲内容, 还有 Weex 以及 Flutter, 这里做一个对比.
混合开发框架比较
| 框架 |
RN |
Weex |
Flutter |
| 公司 |
Facebook |
Alibaba |
Google |
| 语言 |
JS (React) |
JS (Vue) |
Dart |
| 引擎 |
JSCore |
V 8 |
Flutter Engine |
| 系统 |
Android, IOS |
Android, IOS, Web |
Android, IOS, Fuchsia |
| 性能 |
一般 |
较快 |
较快 |
| 场景 |
整体 APP |
单页面 |
整体 APP |
| 学习成本 |
难 |
易 |
一般 |
RN 的优势
- 开发体验好. 用统一的代码规范开发移动端程序, 不需要关注移动端的差异.
- 开发成本低. 一次开发多端部署.
- 学习成本低. 只需要掌握 JS 和 react, 就可以开始移动端开发了.
RN 的不足
- 项目版本更新维护较为频繁, 学习成本高.
- 试错成本高, 有些问题没有解决方案.
- 性能不如原生.
- 涉及底层功能的时候, 还是需要针对 Android 和 iOS 进行针对开发.
React Native 基础环境搭建
基础环境
首先, 需要安装 NodeJS (>=12), 这里不过多介绍. 随后, 我们需要安装一下 React Native 的脚手架:
[!bug] 注意
不建议全局安装脚手架, 建议直接跳过本部分.
1 2 3 4 5
| # 全局安装脚手架 npm install -g react-native-cli
# 卸载全局脚手架 npm uninstall -g react-native-cli @react-native-community/cli
|
安卓环境
如果使用的是 Windows, 那么只能搭建安卓开发环境, 不能搭建 iOS 的开发环境, 因为 Swift 编译器只能在 iOS 桌面端使用.
为了搭建安卓的开发环境, 首先我们需要安装 JDK, 也就是需要一个 Java 环境. 这里使用的 JDK 版本请查阅当前的文档内容, 我的文档内容如下:

其次, 安装一下 Android Studio, 直接下载就好:

下载还好, 不需要翻墙; 启动的时候会安装一些对应的组件, 这里需要 翻墙, 否则可能会出现无法正常安装的情况.
[!warning] 注意
安装时间可能非常久, 一定要有耐心.
随后, 需要安装一下 Android SDK, 这里还是查阅一下官方文档的说明再进行安装:

然后来到 Studio, 选择对应的版本进行安装.

SDK Tool 应该会自动安装结束, 这里不做介绍.
另外, 还需要配置一下安卓 SDK 的安装环境变量, 创建一个叫做 ANDROID_HOME 的环境变量即可.

此外, 还需要自己创建一个可运行的安卓虚拟机, 否则可能会出现未知报错.

至此, 基本就安装完毕了, 环境变量根据官网配置一下就好.
初始化项目
创建项目
可以使用脚手架工具, 也可以直接使用如下命令:
1 2 3 4 5
| # 脚手架创建 react-native init myProject
# 不需要脚手架 命令创建 npx @react-native-community/cli init AwesomeProject
|

可以看到项目结构如下:

创建项目了, 直接进入目录, 使用如下命令就可以运行了: (记得安装 yarn)
解决报错
如果遇到报错:

直接点我下载安装包, 并且解压到如下路径即可: (如果是别的版本, 下载对应的版本放在对应的文件夹中一样).
1
| C:\Users\<用户名>\.gradle\wrapper\dists\gradle-4.7-all\4cret0dgl5o3b21weaoncl7ys
|
如果遇到没有 NDK 的报错, 请安装如下内容 (NDK 也可以根据报错信息选择正确的版本)

随后, 在项目的 android 目录下, 创建一个 local.properties 文件, 在里面指定一下 ndk 的路径:
1 2
| ndk.dir=C:\\DevEnvs\\Android\\Sdk\\ndk\\27.1.12297006
|
如果遇到下载慢的问题, 可以考虑使用魔法或者直接在网上下载对应内容后覆盖文件夹.
随后再次执行该命令即可, 等待一会很久, 项目就跑起来了:
这里还要注意, 模拟器一定要开机完成才能够正常运行, 否则会报错.

调试工具
模拟器就是自动启动的一个东西, 是跟随 Android Studio 进行安装的, 如果没有安装, 再次进行安装即可; 真机调试需要使用 USB 调试.
一般的, 我们使用模拟器进行调试即可.
基础语法
React 语法
其实就是下面这几个部分:
- JSX 语法
- 组件 (分类, 传参, 属性, 状态)
- 生命周期
- Hook API
- Redux
- 常用的包
如有需要, 可以查看这篇文章: React 学习笔记 | FuMOE, 我在这里仅记录新的东西.
StyleSheet
这是 RN 中用来声明样式的 API. RN 的样式和 CSS 有所不同:
- 没有继承性: 即子元素不会被父元素的样式影响 (Text 组件除外)
- 样式名称采用小驼峰命名 (fontSize)
- 所有尺寸是没有单位的 (
width: 100)
- 有一些特殊的样式名称 (marginHorizontal)
在 RN 中, 可以按照 React 的方式进行样式声明, 也可以按照数组+多个样式对象的方式, 如果属性重叠, 则后面的会覆盖前面的.
创建组件
查看 index.js, 可以看到如下代码:
1 2 3 4 5 6 7 8 9 10 11
|
import { AppRegistry } from 'react-native'; import App from './App'; import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
|
另外, 我们不要原来的 App, 直接新建一个出来.
1 2 3 4 5 6 7 8 9 10 11 12
| import { FC } from 'react'; import { Text, View } from 'react-native';
const App: FC = () => { return ( <View> <Text>Hello World</Text> </View> ); };
export default App;
|
查看发现, 左上角有一个 Hello World 了!

我们也可以直接创建一个 src/components 目录, 写上想要的组件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { FC, useState } from 'react'; import { Text, View, Button } from 'react-native';
const HelloWorld: FC = () => { const [counter, setCounter] = useState(0); return ( <View> <Text>Hello World</Text> <Button title="-1" onPress={() => setCounter(counter - 1)} /> <Text>{counter}</Text> <Button title="+1" onPress={() => setCounter(counter + 1)} /> </View> ); };
export default HelloWorld;
|
随后正常使用该组件即可.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { FC } from 'react'; import { View } from 'react-native'; import HelloWorld from './src/components/HelloWorld';
const App: FC = () => { return ( <View> {/* 正常调用组件 */} <HelloWorld /> </View> ); };
export default App;
|
效果是没有问题的.

行内样式
接下来, 就可以尝试给组件添加样式了, 比如给 text 添加属性.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { FC } from 'react'; import { Text, View } from 'react-native';
const HelloWorld: FC = () => { return ( <View> {/* 注意 RN中是没有单位的 */} <Text style={{ fontSize: 30 }}>Hello World</Text> </View> ); };
export default HelloWorld;
|

数组的行内样式
也可以用数组的方式, 后出现的会覆盖前面出现的.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import { FC } from 'react'; import { Text, View } from 'react-native';
const HelloWorld: FC = () => { return ( <View> {/* 注意 RN中是没有单位的 */} <Text style={{ fontSize: 30 }}>Hello World</Text> <Text style={[ { color: 'orange' }, { fontSize: 25, }, // 如果颜色重复 则会覆盖原来的 { color: 'green' }, ]} > YYt and Lc </Text> </View> ); };
export default HelloWorld;
|

StyleSheet 样式
另外, 就是使用 StyleSheet 声明样式了, 自然需要引入后再使用. 这里需要使用一个方法, 返回的就是可以直接使用的样式了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import { FC } from 'react'; import { Text, View, StyleSheet } from 'react-native';
const styles = StyleSheet.create({ title: { fontSize: 30, fontWeight: 'bold', }, });
const HelloWorld: FC = () => { return ( <View> <Text style={styles.title}>Hello World</Text> </View> ); };
export default HelloWorld;
|
感觉好一些, 避免了行内样式的问题.
Flexbox
手机端的弹性布局和普通的不太一样. 这里有一些 Flexbox 的术语:
- 容器 (container)
- 采用 Flex 布局的元素, 称为 Flex 容器
- 项目 (item)
- 主轴 (main axis)
- 交叉轴 (cross axis)
对应的, 我们可以设置一个 Flex 容器的主轴方向, Web 默认是 row, RN 默认则是 column. 另外还可以设置主轴, 交叉轴的对其方式, 以及一些比例, 基础代码如下.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| import { FC } from 'react'; import { Text, View, StyleSheet } from 'react-native';
const style = StyleSheet.create({ mainContainer: { margin: 20, }, title: { fontSize: 30, fontWeight: 'bold', }, subTitle: { fontSize: 25, fontWeight: 'bold', color: '#333', },
namesContainer: { height: 150, margin: 10, borderWidth: 1, borderColor: '#ddd', },
nameItem: { backgroundColor: 'lightgreen', textAlign: 'center', borderColor: '#000', borderWidth: 1, margin: 5, }, });
const FlexTest: FC = () => { return ( <View style={style.mainContainer}> <Text style={style.title}>Flex布局测试</Text> <Text style={style.subTitle}>主轴方向</Text> <View style={style.namesContainer}> <Text style={style.nameItem}>小猫</Text> <Text style={style.nameItem}>YYT</Text> <Text style={style.nameItem}>LC</Text> </View> </View> ); };
export default FlexTest;
|
显示基础效果如下:

接下来, 可以设置一下方向:
1 2 3 4 5 6 7 8
| namesContainer: { height: 150, margin: 10, borderWidth: 1, borderColor: '#ddd', flexDirection: 'row', },
|

也可以根据需要进行修改, 其实这个就是普通的 flex 布局的包装, 剩下的还是不介绍了.
响应式布局
简单说, 就是让元素根据屏幕的大小进行自适应, 而不是直接写死一个大小. 这里需要用到一个新的东西: Dimensions, 它可以帮助我们获取屏幕的大小以及窗口的大小.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import { FC } from 'react'; import { Text, View, StyleSheet, Dimensions } from 'react-native';
const styles = StyleSheet.create({ container: { flexDirection: 'row', paddingTop: 20, }, h1: { fontSize: 35, fontWeight: 'bold', }, itemBase: { justifyContent: 'center', alignItems: 'center', backgroundColor: '#00b38a', width: Dimensions.get('window').width / 4, height: 80,
borderWidth: 1, borderColor: 'yellow', }, itemText: { fontSize: 20, color: 'white', fontWeight: 'bold', }, });
const TestComponent: FC = () => { return ( <View style={styles.container}> {/* 模拟一个响应式布局 */} <View style={styles.itemBase}> <Text style={styles.itemText}>扫一扫</Text> </View> <View style={styles.itemBase}> <Text style={styles.itemText}>付款码</Text> </View> <View style={styles.itemBase}> <Text style={styles.itemText}>卡包</Text> </View> <View style={styles.itemBase}> <Text style={styles.itemText}>出行</Text> </View> </View> ); };
export default TestComponent;
|
这一行的东西就出现了.

另外, 如果我希望一行是 3 个, 直接修改为 / 3 的话, 会发现最后面的出行没了.

这里需要设置一下换行, flexWrap 属性.
1 2 3 4 5 6
| container: { flexDirection: 'row', flexWrap: 'wrap', paddingTop: 20, },
|
这样显示就正常了.

核心组件
RN 中的核心组件其实就是对原生组件的一些封装, 原生组件就是 Android 或者 IOS 内部就写好的一些直接使用的组件.

其实就是一些非常常用的组件, 还是有必要了解一下的, 不了解也没关系, 直接看文档, 根据需要走就行.
顾名思义, 就是按钮. 直接查看代码及效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import { FC } from 'react'; import { Text, View, StyleSheet, Button, Alert } from 'react-native';
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, gap: 10, }, h1: { fontSize: 30, fontWeight: 'bold', }, });
const TestComponent: FC = () => { return ( <View style={styles.container}> <Text style={styles.h1}>按钮组件</Text> {/* 对于一个按钮来说 需要使用单标签 */} <Button title="Alert" onPress={() => { Alert.alert('按钮点击了'); }} />
{/* 可以设置颜色 */} <Button title="Alert" onPress={() => { Alert.alert('按钮2点击了'); }} // 可以配置颜色 color={'red'} /> </View> ); };
export default TestComponent;
|

Alert
其实就是一个对话框. 使用的时候配合按钮一起使用即可. 按钮的点击事件是 onPress:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| import { FC } from 'react'; import { Text, View, StyleSheet, Button, Alert } from 'react-native';
const style = StyleSheet.create({ mainContainer: { margin: 10, gap: 10, }, title: { fontSize: 35, fontWeight: 'bold', }, });
const FlexTest: FC = () => { return ( <View style={style.mainContainer}> <Text style={style.title}>Alert测试</Text> {/* 使用的时候 使用的是 title来指定 */} <Button title="我是一个按钮" onPress={() => { // 通过Alert来触发弹窗 Alert.alert('我是一个弹窗'); }} /> <Button title="多个按钮的弹窗" onPress={() => { // 通过Alert来触发弹窗 Alert.alert('我是标题', '我是消息内容', [ { text: '按钮1', onPress: () => console.log('点击按钮1'), }, { text: '按钮2', onPress: () => console.log('点击按钮2'), }, ]); }} />
<Button title="选项文本可以自定义样式" onPress={() => { Alert.alert('我是标题', '我是消息内容', [ { text: '按钮1', style: 'destructive', onPress: () => console.log('点击按钮1'), }, { text: '按钮2', style: 'cancel', onPress: () => console.log('点击按钮2'), }, ]); }} /> </View> ); };
export default FlexTest;
|
这就是基础的点击事件了.

StatusBar
这个就是手机最上面的, 显示电量之类内容的地方. 可以通过一个布尔值开控制开关.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import { FC } from 'react'; import { Text, View, StyleSheet, StatusBar } from 'react-native';
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, gap: 10, }, h1: { fontSize: 30, fontWeight: 'bold', }, });
const TestComponent: FC = () => { return ( <View style={styles.container}> <StatusBar // 是否显示 hidden={false} backgroundColor={'red'} // 设置图标的颜色 barStyle={'dark-content'} /> <Text style={styles.h1}>设置状态栏</Text> </View> ); };
export default TestComponent;
|
然后就可以看到上面的这个 Bar 了.

Switch
就是一个简单的开关按钮, 可以配合上面的 StatusBar 来进行练习.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import { FC, useState } from 'react'; import { Text, View, StyleSheet, StatusBar, Switch } from 'react-native';
const styles = StyleSheet.create({ container: { justifyContent: 'center', alignItems: 'center', padding: 20, gap: 10, }, h1: { fontSize: 30, fontWeight: 'bold', }, });
const TestComponent: FC = () => { const [showStatusBar, setShowStatusBar] = useState(true); return ( <View style={styles.container}> <Text style={styles.h1}>设置状态栏</Text> <StatusBar // 是否显示 hidden={showStatusBar} backgroundColor={'red'} // 设置图标的颜色 barStyle={'dark-content'} /> <Switch // 设置颜色 trackColor={{ false: 'red', true: 'green' }} // 小圆点的颜色 thumbColor={'blue'} // 设置值 value={showStatusBar} // 实现切换 onValueChange={setShowStatusBar} /> </View> ); };
export default TestComponent;
|

矢量图标库
有的时候我们可能会遇到需要使用图标按钮之类的情况, 这个时候我们就可以直接使用这个第三方组件库了.
直接使用如下命令进行安装: (这里查阅文档, 根据需要安装需要的即可)
1
| npm install @react-native-vector-icons/fontawesome6 @react-native-vector-icons/evil-icons
|
对于安卓来说, 最新版已经不需要链接图标库之类的操作了, 直接重新编译程序即可.
路由导航
基础安装
一个程序自然有很多的页面, 我的, 设置这种, 一堆一堆. 那么我们自然就需要使用路由了. 在 RN 中, 我们使用的是 React Navigation 这个路由, 不是网页端的 React Router, 这俩是不一样的.
[!important] 注意
这里使用的路由版本为 5.x, 不是最新版.
我们使用的不是 expo, 所以可以忽略一些东西. 下面这些是必须要进行安装的:
1 2 3 4 5
| # 安装核心 npm install @react-navigation/native@^5.x
# 安装依赖 npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
|
随后, 需要进行配置, 来到程序的顶部, 也就是 App.tsx 或者 index.js, 可以进行注册.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { Text, View } from "react-native";
import "react-native-gesture-handler"; import { NavigationContainer } from "@react-navigation/native";
function App() { return ( <NavigationContainer> <View> <Text>Hello World</Text> </View> </NavigationContainer> ); }
export default App;
|
至此, 基本的配置就算结束了.
Stack 导航
RN 中没有类似浏览器的 History 对象, 所以我们不能通过这个东西进行跳转. 在 RN 中跳转之前, 需要先将路由声明在 Stack 中, 才能进行跳转.
安装
Stack 导航也是要单独进行安装的, 否则不能正常使用.
1
| npm install @react-navigation/stack@^5.x
|
基础使用
参考如下代码进行使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import { StyleSheet, Text, View } from "react-native";
import "react-native-gesture-handler"; import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
const Stack = createStackNavigator();
const HomeScreen = (props) => { return ( <View style={styles.container}> <Text style={[styles.text]}>This is Home Screen</Text> </View> ); };
const DetailScreen = (props) => { return ( <View style={styles.container}> <Text style={[styles.text]}>This is Detail Screen</Text> </View> ); };
function App() { return ( <NavigationContainer> {/* 声明导航的详细内容 */} <Stack.Navigator> {/* 这就是一个容器 包含了多个路由 */} {/* screen就是单个项目 需要name, 路由名称以及component, 路由显示的内容 */} {/* 默认加载的是第一个 Home */} <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Detail" component={DetailScreen} /> </Stack.Navigator> </NavigationContainer> ); }
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", }, text: { fontSize: 30, }, });
export default App;
|
可以看到显示的效果还是很不错的.

但是目前没法跳转, 我们实现以下跳转的效果.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| const HomeScreen = ({ navigation }) => { return ( <View style={styles.container}> <Text style={[styles.text]}>This is Home Screen</Text> <Button title="前往详情页" onPress={() => { // 这里使用props里面的一个东西进行跳转 // 通过名称进行跳转 navigation.navigate("Detail"); }} /> </View> ); };
const DetailScreen = ({ navigation }) => { return ( <View style={styles.container}> <Text style={[styles.text]}>This is Detail Screen</Text> <Button title="跳转到主页" onPress={() => { navigation.navigate("Home"); }} /> </View> ); };
|
现在, 点击就可以触发跳转效果了.

常用属性
默认页面
现在默认加载的是 Home 页面, 如果我希望默认加载别的页面, 可以配置一个属性:
1 2 3 4 5 6 7 8 9 10 11 12
| function App() { return ( <NavigationContainer> {/* 配置初识路由名称 */} <Stack.Navigator initialRouteName="Detail"> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Detail" component={DetailScreen} /> </Stack.Navigator> </NavigationContainer> ); }
|
现在默认的页面就变了:

顶栏隐藏
默认的我们顶部有一个 Header, 我们可能想要去除这个东西, 就可以使用 headerMode 属性.
1 2 3 4 5 6 7 8 9 10 11
| function App() { return ( <NavigationContainer> {/* none 就是没了 */} <Stack.Navigator headerMode="none"> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Detail" component={DetailScreen} /> </Stack.Navigator> </NavigationContainer> ); }
|

这样页面就清爽多了.
顶栏配置
自然, 顶栏的文本之类的东西都是可以配置的, 比如配置标题, 样式.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <NavigationContainer> {} <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} options={{ // 标题 title: "首页", // 样式 headerStyle: { backgroundColor: "lightblue", }, // 也可以配置右边有一个按钮 headerRight: () => ( <TouchableOpacity onPress={() => { Alert.alert("Hello"); }} > <Text>Hello</Text> </TouchableOpacity> ), }} /> <Stack.Screen name="Detail" component={DetailScreen} /> </Stack.Navigator> </NavigationContainer>
|
现在就可以看到顶栏的变化了.

BottomTab 导航
其实就是下面的底部导航栏啦, 使用的规范还是符合第三方组件的使用规范的.
安装
直接在项目中执行如下命令即可:
1
| npm install @react-navigation/bottom-tabs@^5.x
|
基础使用
和 Stack 的一样, 引入后进行实例化, 然后配置即可.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import "react-native-gesture-handler"; import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; const BottomTabNavigator = createBottomTabNavigator();
import HomeScreen from "./src/views/HomeScreen"; import DetailScreen from "./src/views/DetailScreen";
function App() { return ( <NavigationContainer> <BottomTabNavigator.Navigator> <BottomTabNavigator.Screen name="Home" component={HomeScreen} /> <BottomTabNavigator.Screen name="Detail" component={DetailScreen} /> </BottomTabNavigator.Navigator> </NavigationContainer> ); }
export default App;
|
可以看到, 下面已经出现一个底部导航栏了, 并且点击可以切换到不同的页面.

常用属性
图标
作为底部导航栏, 肯定是需要一个图标的. 所以我们需要进行一个配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function App() { return ( <NavigationContainer> {/* 在总体部分配置图标 */} <BottomTabNavigator.Navigator screenOptions={(route) => ({ // focused 当前菜单是否活跃 // color 颜色 // size 大小 // eslint-disable-next-line react/no-unstable-nested-components tabBarIcon: ({ color }) => { let iconName; if (route.route.name === "Home") { iconName = "主页"; } else { iconName = "详情"; } return <Button title={iconName} color={color} />; }, })} > <BottomTabNavigator.Screen name="Home" component={HomeScreen} /> <BottomTabNavigator.Screen name="Detail" component={DetailScreen} /> </BottomTabNavigator.Navigator> </NavigationContainer> ); }
|
这里暂时用一个按钮替代图标, 使用一个配置函数来实现效果.

然而, 这样太丑了, 我们需要的肯定是一个小图标那种样子. 这里可以使用之前配置好的矢量图标库. 随后直接使用即可.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import "react-native-gesture-handler"; import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; const BottomTabNavigator = createBottomTabNavigator();
import HomeScreen from "./src/views/HomeScreen"; import DetailScreen from "./src/views/DetailScreen";
import Icon from "@react-native-vector-icons/ionicons";
function App() { return ( <NavigationContainer> {/* 在总体部分配置图标 */} <BottomTabNavigator.Navigator screenOptions={(route) => ({ tabBarIcon: ({ focused, color, size }) => { return <Icon name="key" size={size} color={color} />; }, })} > <BottomTabNavigator.Screen name="Home" component={HomeScreen} /> <BottomTabNavigator.Screen name="Detail" component={DetailScreen} /> </BottomTabNavigator.Navigator> </NavigationContainer> ); }
export default App;
|
另外需要在 android/app.build.gradle 的文件末尾加上这么一句:
1
| apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
|
然后效果就有啦~ 但是这里配置可能会出现问题, 直接查看官方文档即可.

颜色
另外一个配置项, 可以单独配置颜色.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function App() { return ( <NavigationContainer> {/* 在总体部分配置图标 */} <BottomTabNavigator.Navigator // 配置颜色 在另外一个配置项 tabBarOptions={{ activeTintColor: "blue", inactiveTintColor: "red", }} > <BottomTabNavigator.Screen name="Home" component={HomeScreen} /> <BottomTabNavigator.Screen name="Detail" component={DetailScreen} /> </BottomTabNavigator.Navigator> </NavigationContainer> ); }
|
现在就可以看到颜色了:

Drawer 导航
就是侧边的抽屉导航菜单, 符合第三方组件的使用方式.