在 Web 浏览器中,您可以使用锚 ( <a>) 标签链接到不同的页面。当用户点击一个链接时,该 URL 被推送到浏览器历史堆栈。当用户按下后退按钮时,浏览器会从历史堆栈顶部弹出该项目,因此活动页面现在是之前访问过的页面。但是React Native 没有像 Web 浏览器那样内置的全局历史堆栈概念——所以我们就开始 React Navigation 进行了了解。
React Navigation 的原生堆栈导航器为您的应用程序提供了一种在屏幕之间转换和管理导航历史记录的方法。如果您的应用程序仅使用一个堆栈导航器,那么它在概念上类似于 Web 浏览器处理导航状态的方式 - 您的应用程序在用户与其交互时从导航堆栈中推送和弹出项目,这会导致用户看到不同的屏幕。这在 Web 浏览器和 React Navigation 中的工作方式之间的一个关键区别在于,React Navigation 的本机堆栈导航器提供了您在 Android 和 iOS 上在堆栈中的路由之间导航时所期望的手势和动画。
让我们从演示最常见的导航器开始,createNativeStackNavigator.

安装 stack导航器核心库

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

  1. # npm
  2. npm install @react-navigation/native-stack
  3. # yarn
  4. yarn add @react-navigation/native-stack

💡@react-navigation/native-stack依赖于我们在快速开始部分react-native-screens中安装的其他库。如果您还没有安装这些,请转到该页面并按照安装说明进行操作。

创建一个stack导航器

createNativeStackNavigator是一个函数,它返回一个包含 2 个属性的对象:ScreenNavigator. 它们都是用于配置导航器的 React 组件。Navigator应该包含元素作为其子元素,Screen以定义路由的配置。
NavigationContainer是一个管理我们的导航树并包含导航状态的组件。该组件必须包装所有导航器结构。通常,我们会在应用程序的根目录渲染这个组件,这通常是从App.js.

  1. // In App.js in a new project
  2. import * as React from 'react';
  3. import { View, Text } from 'react-native';
  4. import { NavigationContainer } from '@react-navigation/native';
  5. import { createNativeStackNavigator } from '@react-navigation/native-stack';
  6. function HomeScreen() {
  7. return (
  8. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  9. <Text>Home Screen</Text>
  10. </View>
  11. );
  12. }
  13. const Stack = createNativeStackNavigator();
  14. function App() {
  15. return (
  16. <NavigationContainer>
  17. <Stack.Navigator>
  18. <Stack.Screen name="Home" component={HomeScreen} />
  19. </Stack.Navigator>
  20. </NavigationContainer>
  21. );
  22. }
  23. export default App;

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

路由名称的大小写无关紧要——你可以使用小写home或大写Home,这取决于你。我们更喜欢将我们的路线名称大写。 屏幕唯一需要的配置是namecomponent道具。您可以在本机堆栈导航器参考中阅读有关其他可用选项的更多信息。

配置导航器

所有的路由配置都被指定为我们导航器的道具。我们没有将任何道具传递给我们的导航器,所以它只是使用默认配置。
让我们向我们的原生stack导航器添加第二个屏幕,并将Home屏幕配置为首先渲染:

  1. function DetailsScreen() {
  2. return (
  3. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  4. <Text>Details Screen</Text>
  5. </View>
  6. );
  7. }
  8. const Stack = createNativeStackNavigator();
  9. function App() {
  10. return (
  11. <NavigationContainer>
  12. <Stack.Navigator initialRouteName="Home">
  13. <Stack.Screen name="Home" component={HomeScreen} />
  14. <Stack.Screen name="Details" component={DetailsScreen} />
  15. </Stack.Navigator>
  16. </NavigationContainer>
  17. );
  18. }

现在我们的堆栈有两条路线,一条Home路线和一条Details路线。可以使用Screen组件指定路由。该Screen组件接受一个name对应于我们将用于导航的路线名称的component道具,以及一个对应于它将呈现的组件的道具。
这里,Home路由对应HomeScreen组件,Details路由对应DetailsScreen组件。堆栈的初始路由是Home路由。尝试将其更改为Details并重新加载应用程序(如您所料,React Native 的快速刷新不会更新从 的更改initialRouteName),请注意您现在将看到Details屏幕。然后将其更改回Home并再次重新加载。

注意:componentprop接受组件,而不是渲染函数。不要传递内联函数(例如component={() => <HomeScreen />}),否则当父组件重新渲染时,您的组件将卸载并重新安装丢失所有状态。有关替代方案,请参阅传递其他道具

传递选项

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

  1. <Stack.Screen
  2. name="Home"
  3. component={HomeScreen}
  4. options={{ title: 'Overview' }}
  5. />

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

额外的Props属性

有时我们可能想要将额外的道具传递给屏幕。我们可以通过 2 种方法做到这一点:

  1. 使用React 上下文并使用上下文提供程序包装导航器以将数据传递到屏幕(推荐)。
  2. 为屏幕使用渲染回调而不是指定component道具:
    1. <Stack.Screen name="Home">
    2. {props => <HomeScreen {...props} extraData={someData} />}
    3. </Stack.Screen>

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

下一步

此时的自然问题是:“我如何从Home路线到Details路线?”。这将在下一节中介绍。

小结

  • React Native 没有像 Web 浏览器那样内置的导航 API。React Navigation 为您提供了这一点,以及用于在屏幕之间转换的 iOS 和 Android 手势和动画。
  • Stack.Navigator是一个组件,它将路由配置作为其子组件,并带有用于配置的附加道具并呈现我们的内容。
  • 每个Stack.Screen组件都有一个name prop 引用路由的名称,component prop 指定要为路由渲染的组件。这是 2 个必需的道具。
  • 要指定堆栈中的初始路由是什么,请提供一个initialRouteName作为导航器的道具。
  • 要指定特定于屏幕的选项,我们可以将options prop 传递给Stack.Screen,对于常用选项,我们可以传递screenOptionsStack.Navigator