React Navigation 入门
在网页浏览器中,您可以使用锚点 (<a>
) 标签链接到不同的页面。当用户点击链接时,URL 会被推送到浏览器历史记录堆栈中。当用户按下后退按钮时,浏览器会从历史记录堆栈的顶部弹出该项,因此活动页面现在是之前访问的页面。React Native 没有像网页浏览器那样内置的全局历史记录堆栈的概念——这就是 React Navigation 进入故事的地方。
React Navigation 的原生堆栈导航器提供了一种方法,可以让您的应用程序在屏幕之间进行转换并管理导航历史记录。如果您的应用程序只使用一个堆栈导航器,那么它在概念上类似于网页浏览器处理导航状态的方式——您的应用程序在用户与之交互时将项目推送到导航堆栈并从导航堆栈中弹出项目,这会导致用户看到不同的屏幕。网页浏览器和 React Navigation 之间工作方式的关键区别在于,React Navigation 的原生堆栈导航器提供了在 Android 和 iOS 上在堆栈中路由之间导航时所期望的手势和动画。
让我们从演示最常见的导航器 createNativeStackNavigator
开始。
安装原生堆栈导航器库
到目前为止,我们安装的库是导航器的构建块和共享基础,React Navigation 中的每个导航器都位于自己的库中。要使用原生堆栈导航器,我们需要安装 @react-navigation/native-stack
- npm
- Yarn
- pnpm
npm install @react-navigation/native-stack
yarn add @react-navigation/native-stack
pnpm add @react-navigation/native-stack
💡
@react-navigation/native-stack
依赖于react-native-screens
和我们在 入门 中安装的其他库。如果你还没有安装它们,请前往该页面并按照安装说明操作。
创建原生堆栈导航器
createNativeStackNavigator
是一个函数,它返回一个包含 2 个属性的对象:Screen
和 Navigator
。它们都是用于配置导航器的 React 组件。Navigator
应该包含 Screen
元素作为其子元素,以定义路由的配置。
NavigationContainer
是一个组件,它管理我们的导航树并包含 导航状态。此组件必须包装所有导航器结构。通常,我们会在应用程序的根目录渲染此组件,通常是 App.js
中导出的组件。
// In App.js in a new project
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;
如果你运行此代码,你将看到一个屏幕,其中包含一个空的导航栏和一个灰色内容区域,其中包含你的 HomeScreen
组件(如上所示)。你看到的导航栏和内容区域的样式是堆栈导航器的默认配置,我们将在后面学习如何配置它们。
路由名称的大小写无关紧要 - 你可以使用小写 home
或大写 Home
,由你决定。我们更喜欢将路由名称大写。
配置导航器
所有路由配置都作为属性指定给我们的导航器。我们没有向导航器传递任何属性,因此它只使用默认配置。
让我们向我们的原生堆栈导航器添加第二个屏幕,并配置 Home
屏幕以先渲染
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 initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
现在我们的堆栈有两个路由,一个 Home
路由和一个 Details
路由。可以使用 Screen
组件指定路由。Screen
组件接受一个 name
属性,它对应于我们将用于导航的路由名称,以及一个 component
属性,它对应于它将渲染的组件。
这里,Home
路由对应于 HomeScreen
组件,Details
路由对应于 DetailsScreen
组件。堆栈的初始路由是 Home
路由。尝试将其更改为 Details
并重新加载应用程序(React Native 的快速刷新不会像预期的那样更新来自 initialRouteName
的更改),请注意您现在将看到 Details
屏幕。然后将其更改回 Home
并再次重新加载。
component
属性接受组件,而不是渲染函数。不要传递内联函数(例如 component={() => <HomeScreen />}
),否则您的组件将在父组件重新渲染时卸载并重新挂载,从而丢失所有状态。有关替代方案,请参阅 传递附加属性。
指定选项
导航器中的每个屏幕都可以为导航器指定一些选项,例如在标题中渲染的标题。这些选项可以在每个屏幕组件的 options
属性中传递
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Overview' }}
/>
有时我们希望为导航器中的所有屏幕指定相同的选项。为此,我们可以将 screenOptions
属性传递给导航器。
传递附加属性
有时我们可能希望将附加属性传递给屏幕。我们可以通过两种方法来实现
-
使用 React 上下文 并使用上下文提供者包装导航器以将数据传递给屏幕(推荐)。
-
使用屏幕的渲染回调,而不是指定
component
属性<Stack.Screen name="Home">
{(props) => <HomeScreen {...props} extraData={someData} />}
</Stack.Screen>
默认情况下,React Navigation 对屏幕组件应用优化以防止不必要的渲染。使用渲染回调会删除这些优化。因此,如果您使用渲染回调,您需要确保使用 React.memo
或 React.PureComponent
作为您的屏幕组件,以避免性能问题。
下一步
此时自然而然的问题是:“如何从 Home
路由导航到 Details
路由?”。这将在 下一节 中介绍。
总结
- React Native 没有像 Web 浏览器那样的内置导航 API。React Navigation 为您提供了这一点,以及 iOS 和 Android 的手势和动画,用于在屏幕之间进行过渡。
Stack.Navigator
是一个组件,它将路由配置作为其子元素,并带有用于配置的附加属性,并渲染我们的内容。- 每个
Stack.Screen
组件都需要一个name
属性,它指的是路由的名称,以及一个component
属性,它指定了要为该路由渲染的组件。 这是两个必需的属性。 - 要指定堆栈中的初始路由,请为导航器提供一个
initialRouteName
属性。 - 要指定特定于屏幕的选项,我们可以将
options
属性传递给Stack.Screen
,对于通用选项,我们可以将screenOptions
传递给Stack.Navigator
。