最近两个项目都用到了 React Navigation,因此对其使用进行了研究。本文主要介绍 react-navigation 6.x 路由库的基本使用方法。
React Native 项目初始化
首先,打开命令行,切换到要创建 React Native 项目的文件夹,执行以下命令初始化项目:
npx react-native init testRN
这里将项目名设置为 testRN,可根据需要自行修改。
安装 React Native 项目
连接安卓虚拟机或通过 USB 调试的真机,进入创建好的项目根目录,运行 yarn android 安装并启动应用。初次安装完成后,若手机保持连接,后续只需在虚拟机或手机上打开项目应用,然后在 PC 的项目根目录运行 yarn start 启动即可,无需重新安装。若连接断开,可能需要重新安装。启动后,在命令行界面按 r 键可以更新应用。
React Navigation 路由库安装
以下内容基于 Android 端测试,iOS 端未进行验证。一次性安装以下包:
yarn add @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/native-stack
对于安卓端,需要进行额外配置。修改 testRN\android\app\src\main\java\com\testrn 目录下的 MainActivity.java 文件,添加以下代码:
import android.os.Bundle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
}
使用路由库
将 app.js 修改为以下代码:
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
路由跳转与路由传参
以下示例展示如何实现路由跳转和传参:
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
function HomeScreen({navigation}) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
设置路由标题
默认情况下,窗口会使用 name 属性作为标题名,但也可以自行设定。例如:
<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'my home' }} />
这里用 "my home" 代替 "Home" 作为导航标题。当从一级页面跳转到二级页面时,可能需要根据内容动态展示不同标题,此时可以动态配置 title:
<Stack.Screen name="Details" component={DetailsScreen}
options={({ route }) => ({ title: route.params.title })}
/>
然后在一级页面跳转时传递 title 参数:
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details', { title: '二级页面' })}
/>
注意,如果一级页面没有传递 title,最好传递一个空对象或在二级页面设置初始值,以避免报错。此外,还可以使用 navigation.setOptions() 手动更新标题,该方法修改的是 screen 上 options 中的属性:
<Button
title="Update the title"
onPress={() => navigation.setOptions({ title: 'Updated!' })}
/>
自定义标题组件
通过设置 headerTitle 回调返回一个函数式组件,可以自定义标题,例如使用图片:
function LogoTitle() {
return (
<Image
style={{ width: 50, height: 50 }}
source={require('./src/img/details.png')}
/>
);
}
<Stack.Screen name="Home" component={HomeScreen}
options={{
title: 'My home',
headerTitle: (props) => <LogoTitle {...props} />
}}
/>
标题按钮
在 screen 的 options 中,可以使用 headerRight 添加按钮:
<Stack.Screen name="Home" component={HomeScreen}
options={{
title: 'My home',
headerTitle: (props) => <LogoTitle {...props} />,
headerRight: () => (
<Button
onPress={() => alert('This is a button!')}
title="Info"
color="#fff"
/>
),
}}
此外,headerBackImageSource 可以修改回退按钮的图片:
<Stack.Screen name="Details" component={DetailsScreen}
options={({ route }) => ({
title: route.params.title,
headerBackImageSource: detailsImg,
})}
/>