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