Skip to main content
Version: 6.x

你好 React 导航

在网络浏览器中,你可以使用锚点 (<a>) 标签链接到不同的页面。当用户单击链接时,URL 会被推送到浏览器历史记录堆栈中。当用户按下后退按钮时,浏览器会从历史堆栈顶部弹出该项目,因此活动页面现在是以前访问过的页面。React Native 不像 Web 浏览器那样具有全局历史堆栈的内置概念 - 这就是 React Navigation 的用武之地。

¥In a web browser, you can link to different pages using an anchor (<a>) tag. When the user clicks on a link, the URL is pushed to the browser history stack. When the user presses the back button, the browser pops the item from the top of the history stack, so the active page is now the previously visited page. React Native doesn't have a built-in idea of a global history stack like a web browser does -- this is where React Navigation enters the story.

React Navigation 的原生堆栈导航器为你的应用提供了一种在屏幕之间转换和管理导航历史记录的方法。如果你的应用仅使用一个堆栈导航器,那么它在概念上类似于网络浏览器处理导航状态的方式 - 当用户与应用交互时,你的应用会从导航堆栈中推送和弹出项目,这会导致用户看到不同的屏幕。在 Web 浏览器和 React Navigation 中的工作方式之间的一个关键区别在于,React Navigation 的原生堆栈导航器提供了你在 Android 和 iOS 上在堆栈中的路由之间导航时所期望的手势和动画。

¥React Navigation's native stack navigator provides a way for your app to transition between screens and manage navigation history. If your app uses only one stack navigator then it is conceptually similar to how a web browser handles navigation state - your app pushes and pops items from the navigation stack as users interact with it, and this results in the user seeing different screens. A key difference between how this works in a web browser and in React Navigation is that React Navigation's native stack navigator provides the gestures and animations that you would expect on Android and iOS when navigating between routes in the stack.

我们先来演示一下最常见的导航器 createNativeStackNavigator

¥Let's start by demonstrating the most common navigator, createNativeStackNavigator.

安装原生堆栈导航器库

¥Installing the native stack navigator library

到目前为止,我们安装的库是导航器的构建块和共享基础,React Navigation 中的每个导航器都位于自己的库中。要使用原生堆栈导航器,我们需要安装 @react-navigation/native-stack

¥The libraries we've installed so far are the building blocks and shared foundations for navigators, and each navigator in React Navigation lives in its own library. To use the native stack navigator, we need to install @react-navigation/native-stack :

npm install @react-navigation/native-stack

💡 @react-navigation/native-stack 依赖于 react-native-screens 以及我们在 入门 中安装的其他库。如果你还没有安装这些,请转到该页面并按照安装说明进行操作。

¥💡 @react-navigation/native-stack depends on react-native-screens and the other libraries that we installed in Getting started. If you haven't installed those yet, head over to that page and follow the installation instructions.

创建原生堆栈导航器

¥Creating a native stack navigator

createNativeStackNavigator 是一个返回包含 2 个属性的对象的函数:ScreenNavigator。它们都是用于配置导航器的 React 组件。Navigator 应包含 Screen 元素作为其子元素来定义路由的配置。

¥createNativeStackNavigator is a function that returns an object containing 2 properties: Screen and Navigator. Both of them are React components used for configuring the navigator. The Navigator should contain Screen elements as its children to define the configuration for routes.

NavigationContainer 是管理我们的导航树并包含 导航状态 的组件。该组件必须封装所有导航器结构。通常,我们会在应用的根目录渲染此组件,该组件通常是从 App.js 导出的组件。

¥NavigationContainer is a component which manages our navigation tree and contains the navigation state. This component must wrap all navigators structure. Usually, we'd render this component at the root of our app, which is usually the component exported from 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;

Basic app using stack navigator

如果运行此代码,你将看到一个屏幕,其中有一个空的导航栏和一个包含 HomeScreen 组件的灰色内容区域(如上所示)。你看到的导航栏和内容区域的样式是堆栈导航器的默认配置,我们稍后将学习如何配置它们。

¥If you run this code, you will see a screen with an empty navigation bar and a grey content area containing your HomeScreen component (shown above). The styles you see for the navigation bar and the content area are the default configuration for a stack navigator, we'll learn how to configure those later.

提示

路由名称的大小写并不重要 - 你可以使用小写 home 或大写 Home,这取决于你。我们更喜欢将路由名称大写。

¥The casing of the route name doesn't matter -- you can use lowercase home or capitalized Home, it's up to you. We prefer capitalizing our route names.

配置导航器

¥Configuring the navigator

所有的路由配置都被指定为我们的导航器的属性。我们没有向导航器传递任何属性,因此它只使用默认配置。

¥All of the route configuration is specified as props to our navigator. We haven't passed any props to our navigator, so it just uses the default configuration.

让我们向原生堆栈导航器添加第二个屏幕,并将 Home 屏幕配置为首先渲染:

¥Let's add a second screen to our native stack navigator and configure the Home screen to render first:

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 属性,它对应于它将渲染的组件。

¥Now our stack has two routes, a Home route and a Details route. A route can be specified by using the Screen component. The Screen component accepts a name prop which corresponds to the name of the route we will use to navigate, and a component prop which corresponds to the component it'll render.

这里,Home 路由对应于 HomeScreen 组件,Details 路由对应于 DetailsScreen 组件。堆栈的初始路由是 Home 路由。尝试将其更改为 Details 并重新加载应用(React Native 的快速刷新不会更新 initialRouteName 的更改,如你所料),请注意,你现在将看到 Details 屏幕。然后将其更改回 Home 并再次重新加载。

¥Here, the Home route corresponds to the HomeScreen component, and the Details route corresponds to the DetailsScreen component. The initial route for the stack is the Home route. Try changing it to Details and reload the app (React Native's Fast Refresh won't update changes from initialRouteName, as you might expect), notice that you will now see the Details screen. Then change it back to Home and reload once more.

警告

component 属性接受组件,而不是渲染函数。不要传递内联函数(例如 component={() => <HomeScreen />}),否则当父组件重新渲染时,你的组件将卸载并重新安装,从而丢失所有状态。请参阅 传递额外的属性 了解替代方案。

¥The component prop accepts component, not a render function. Don't pass an inline function (e.g. component={() => <HomeScreen />}), or your component will unmount and remount losing all state when the parent component re-renders. See Passing additional props for alternatives.

指定选项

¥Specifying options

导航器中的每个屏幕都可以为导航器指定一些选项,例如要在标题中呈现的标题。这些选项可以在每个屏幕组件的 options 属性中传递:

¥Each screen in the navigator can specify some options for the navigator, such as the title to render in the header. These options can be passed in the options prop for each screen component:

<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Overview' }}
/>

有时我们希望为导航器中的所有屏幕指定相同的选项。为此,我们可以将 screenOptions 属性传递给导航器。

¥Sometimes we will want to specify the same options for all of the screens in the navigator. For that, we can pass a screenOptions prop to the navigator.

传递额外的属性

¥Passing additional props

有时我们可能想将额外的属性传递到屏幕。我们可以通过两种方法来做到这一点:

¥Sometimes we might want to pass additional props to a screen. We can do that with 2 approaches:

  1. 使用 React 上下文 并使用上下文提供程序封装导航器以将数据传递到屏幕(推荐)。

    ¥Use React context and wrap the navigator with a context provider to pass data to the screens (recommended).

  2. 使用屏幕的渲染回调而不是指定 component 属性:

    ¥Use a render callback for the screen instead of specifying a component prop:

    <Stack.Screen name="Home">
    {(props) => <HomeScreen {...props} extraData={someData} />}
    </Stack.Screen>
警告

默认情况下,React Navigation 会对屏幕组件进行优化,以防止不必要的渲染。使用渲染回调可以消除这些优化。因此,如果你使用渲染回调,则需要确保对屏幕组件使用 React.memoReact.PureComponent 以避免出现性能问题。

¥By default, React Navigation applies optimizations to screen components to prevent unnecessary renders. Using a render callback removes those optimizations. So if you use a render callback, you'll need to ensure that you use React.memo or React.PureComponent for your screen components to avoid performance issues.

下一步是什么?

¥What's next?

此时自然的问题是:“如何从 Home 路由转到 Details 路由?”。下一节 中对此进行了介绍。

¥The natural question at this point is: "how do I go from the Home route to the Details route?". That is covered in the next section.

概括

¥Summary

  • React Native 没有像 Web 浏览器那样的内置导航 API。React Navigation 为你提供了这一点,以及用于在屏幕之间转换的 iOS 和 Android 手势和动画。

    ¥React Native doesn't have a built-in API for navigation like a web browser does. React Navigation provides this for you, along with the iOS and Android gestures and animations to transition between screens.

  • Stack.Navigator 是一个组件,它将路由配置作为其子组件,并具有用于配置的附加属性并呈现我们的内容。

    ¥Stack.Navigator is a component that takes route configuration as its children with additional props for configuration and renders our content.

  • 每个 Stack.Screen 组件都采用 name 属性(指的是路由名称)和 component 属性(指定要为路由渲染的组件)。这是 2 个必需的属性。

    ¥Each Stack.Screen component takes a name prop which refers to the name of the route and component prop which specifies the component to render for the route. These are the 2 required props.

  • 要指定堆栈中的初始路由是什么,请提供 initialRouteName 作为导航器的 prop。

    ¥To specify what the initial route in a stack is, provide an initialRouteName as the prop for the navigator.

  • 要指定特定于屏幕的选项,我们可以将 options 属性传递给 Stack.Screen,对于常见选项,我们可以将 screenOptions 传递给 Stack.Navigator

    ¥To specify screen-specific options, we can pass an options prop to Stack.Screen, and for common options, we can pass screenOptions to Stack.Navigator