Skip to main content

你好 React Navigation

在网页浏览器中,你可以使用锚点标签(<a>)链接到不同的页面。当用户点击链接时,URL会被推入浏览器的历史记录栈中。当用户按下后退按钮时,浏览器会从历史记录栈顶弹出一项,这样当前页面就会回到之前访问的页面。React Native 并没有像网页浏览器那样内置的全局历史记录栈概念 -- 这就是 React Navigation 发挥作用的地方。

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

让我们从演示最常用的导航器 createNativeStackNavigator 开始。

安装原生堆栈导航器库

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

npm install @react-navigation/native-stack
info

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

安装元素库

@react-navigation/elements库提供了一组专门设计用于与 React Navigation 配合使用的组件。我们将在本指南中使用其中的一些组件。所以让我们先安装它:

npm install @react-navigation/elements

创建原生堆栈导航器

createNativeStackNavigator 是一个函数,它接收一个包含页面和自定义选项的配置对象。屏幕是由导航器渲染内容的 React 组件。

createStaticNavigation 是一个函数,它接收之前定义的导航器并返回一个可以在应用中渲染的组件。它在应用中只被调用一次。

// 在新项目的 App.js 中

import * as React from 'react';
import { View, Text } from 'react-native';
import { createStaticNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>首页</Text>
</View>
);
}

const RootStack = createNativeStackNavigator({
screens: {
Home: HomeScreen,
},
});

const Navigation = createStaticNavigation(RootStack);

export default function App() {
return <Navigation />;
}

使用堆栈导航器的基本应用

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

tip

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

配置导航器

所有的路由配置都是作为导航器的 props 指定的。我们还没有给导航器传递任何 props,所以它只使用默认配置。

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

import * as React from 'react';
import { View, Text } from 'react-native';
import { createStaticNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>首页</Text>
</View>
);
}

function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>详情页</Text>
</View>
);
}

const RootStack = createNativeStackNavigator({
initialRouteName: 'Home',
screens: {
Home: HomeScreen,
Details: DetailsScreen,
},
});

const Navigation = createStaticNavigation(RootStack);

export default function App() {
return <Navigation />;
}

现在我们的堆栈有两个_路由_,一个 Home 路由和一个 Details 路由。路由可以在 screens 属性下指定。screens 下的属性名对应于我们将用于导航的路由名称,而值对应于它将渲染的组件。

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

指定选项

导航器中的每个屏幕都可以为导航器指定一些选项,比如在标题栏中渲染的标题。

要指定选项,我们将改变指定屏幕组件的方式。我们可以指定一个带有 screen 属性的对象,而不是将屏幕组件指定为值:

const RootStack = createNativeStackNavigator({
initialRouteName: 'Home',
screens: {
Home: {
screen: HomeScreen,
},
Details: DetailsScreen,
},
});

这将让我们为屏幕指定额外的选项。

现在,我们可以添加一个 options 属性:

import * as React from 'react';
import { View, Text } from 'react-native';
import { createStaticNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>首页</Text>
</View>
);
}

function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>详情页</Text>
</View>
);
}

const RootStack = createNativeStackNavigator({
initialRouteName: 'Home',
screens: {
Home: {
screen: HomeScreen,
options: {
title: '概览',
},
},
Details: DetailsScreen,
},
});

const Navigation = createStaticNavigation(RootStack);

export default function App() {
return <Navigation />;
}

有时我们想为导航器中的所有屏幕指定相同的选项。为此,我们可以在配置中添加一个 screenOptions 属性:

import * as React from 'react';
import { View, Text } from 'react-native';
import { createStaticNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>首页</Text>
</View>
);
}

function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>详情页</Text>
</View>
);
}

const RootStack = createNativeStackNavigator({
initialRouteName: 'Home',
screenOptions: {
headerStyle: { backgroundColor: 'tomato' },
},
screens: {
Home: {
screen: HomeScreen,
options: {
title: '概览',
},
},
Details: DetailsScreen,
},
});

const Navigation = createStaticNavigation(RootStack);

export default function App() {
return <Navigation />;
}

传递额外的 props

静态 API 不支持向屏幕传递额外的 props。

接下来是什么?

此时自然会问:"我如何从 Home 路由转到 Details 路由?"。这将在下一节中介绍。

与 TypeScript 一起使用

如果你使用 TypeScript,你需要相应地指定类型。你可以在学习完基础知识后查看使用 TypeScript 进行类型检查了解更多详情。目前,我们不会在示例中涉及 TypeScript。

总结

  • React Native 没有像网页浏览器那样内置的导航 API。React Navigation 为你提供了这个功能,以及在屏幕之间转换时 iOS 和 Android 的手势和动画。
  • createNativeStackNavigator 是一个接收屏幕配置并渲染我们内容的函数。
  • screens 下的每个属性都指向路由的名称,而值则是要为该路由渲染的组件。
  • 要指定堆栈中的初始路由,需要为导航器提供 initialRouteName 选项。
  • 要指定特定于屏幕的选项,我们可以指定 options 属性,对于通用选项,我们可以指定 screenOptions