跳到主要内容

React Navigation 3.0

·9 分钟阅读
Brent Vatne
核心团队

文档现已上线 reactnavigation.org,v2 版本在此处 here

这是第一个版本,其中 React Navigation 依赖于 React Native 核心之外的原生模块:它现在依赖于 react-native-gesture-handler。此库提供了一组出色的原语,用于利用操作系统的原生手势 API,并使我们能够修复堆叠和抽屉导航器的各种问题。React Navigation 还依赖于 react-native-screens,但如果您不想使用原生模块,则无需安装它(我们即将发布一篇博文,解释 react-native-screens 是什么以及您可能想要使用它的原因,或者您可以观看 此演讲,作者是该库的作者)。

我们没有完成此版本的所有功能,但我们也不想进一步推迟它,因为我们希望您会希望立即开始使用它 - 该版本包括性能改进、错误修复、人体工程学改进、一些方便的新功能,以及内部结构的重新组织,以改进对 Web 作为 React Navigation 目标的支撑。

让我们开始使用 react-navigation 3.0。

安装

首先,使用您喜欢的包管理器安装库: yarn add react-navigation@^3.0.0

接下来,安装 react-native-gesture-handler。如果您使用 Expo,则无需在此处执行任何操作,它已包含在 SDK 中。否则,请按照 这些安装说明 进行操作。

可选地,您可以安装 react-native-screens。如果您使用 Expo,则无需在此处执行任何操作,它已包含在 SDK 30 及更高版本中。否则,请按照 react-native-screens 上的 README 中的说明进行操作。

警告:如果您手动安装了项目中的任何导航器,例如 react-navigation-material-bottom-tabs,您将需要将这些导航器更新到与 3.0.0 兼容的版本。对于 react-navigation-material-bottom-tabs,1.0.0 版本兼容。

重大更改

当您首次运行更新后的应用程序时,它将无法工作,因为 react-navigation@^3 要求您向根导航器添加一个应用容器。一旦您将其安装到位,您可能会注意到您的导航选项未按预期应用 - 这是由于导航器配置中的 navigationOptions 重命名为 defaultNavigationOptions。如果您使用抽屉,您可能会注意到它感觉更快,但如果您依赖于非活动屏幕被卸载,您会感到惊讶。有关这些更改以及如何更新您的应用程序以使其与以前一样好(可能更好)的更多详细信息如下。

根导航器需要显式的应用容器

过去,任何导航器都可以充当应用程序顶层的导航容器,因为它们都包装在“导航容器”中。导航容器(现在称为应用容器)是一个高阶组件,它维护应用程序的导航状态并处理与外部世界的交互,以将链接事件转换为导航操作等等。

import {
createStackNavigator,
createAppContainer
} from 'react-navigation';
const MainNavigator = createStackNavigator({...});
const App = createAppContainer(MainNavigator);

这应该是一个简单的更改 - 在应用程序的根目录中导入 createAppContainer,并使用它来包裹根导航器。

警告:如果您有任何自定义导航器,您可能使用了 createNavigationContainer,您现在可以删除它,因为它仅在应用程序的根目录中使用,并由用户提供。

导航器配置中 navigationOptions 已重命名

配置导航器时,通常需要为该导航器内的屏幕传入默认导航选项。例如,在堆叠中,您可能希望为每个屏幕设置背景颜色和色调颜色。以前,您会这样写

const Home = createStackNavigator(
{
Feed: ExampleScreen,
Profile: ExampleScreen,
},
{
navigationOptions: {
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#000',
},
},
}
);

在此版本中,像这样的导航器配置中的 navigationOptions 已重命名为 defaultNavigationOptions

const Home = createStackNavigator(
{
Feed: ExampleScreen,
Profile: ExampleScreen,
},
{
defaultNavigationOptions: {
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#000',
},
},
}
);

有时您需要配置导航器本身的 navigationOptions。通常您会这样做

Home.navigationOptions = { tabBarLabel: 'Home!' };

在此版本中,您可以改为在此处使用导航器配置中的 navigationOptions

const Home = createStackNavigator(
{
Feed: ExampleScreen,
Profile: ExampleScreen,
},
{
defaultNavigationOptions: {
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#000',
},
},
navigationOptions: {
tabBarLabel: 'Home!',
},
}
);

const Tabs = createBottomTabNavigator({ Home });

在 Snack 上查看此示例.

很抱歉让您去搜索代码并重命名一些字符串,希望此更改使代码更具可读性,并且对未来的新用户更直观。

抽屉导航器现在默认将非活动标签页保留在内存中

以前,当使用抽屉导航器时,屏幕在不活动时会卸载,当您切换回它们时,您需要重新渲染整个内容。在标签页中,这些内容会像您期望的那样保留在内存中,因此一旦您切换到屏幕一次,再次返回那里会更快,并且您不会在滚动视图或任何内容中丢失您的位置。抽屉导航器现在的行为方式相同,但如果您愿意,可以通过在抽屉导航配置中传入 unmountInactiveRoutes: true 来恢复旧的行为。

默认堆叠背景颜色现在为白色

您可以使用 cardStyle 自定义此设置

createStackNavigator(routes, { cardStyle: { backgroundColor: '#ccc' } });

新功能

  • react-navigation 现在导出 ScrollViewFlatListSectionList,当您点击活动标签页时,它们将滚动到顶部,就像您从原生标签栏中期望的那样。
  • 抽屉导航器除了您从典型的 Android 抽屉中期望的默认“前”行为外,还支持另外两种类型:back 和 slide。
  • 您现在可以在路由定义中提供默认参数
const Store = createStackNavigator({
Playstation: { screen: ProductScreen, params: { product: 'Playstation' } },
Xbox: { screen: ProductScreen, params: { product: 'Xbox' } },
});
  • react-navigation-hooks 中对 Hook 的基本支持(尽管在没有支持 Hook 的稳定 react-native 构建的情况下,这还不太有用,您可以在 Web 上玩!)。
  • headerBackgroundTransitionPreset: 'toggle' | 'fade' | 'translate' 让您可以选择如何在屏幕之间转换自定义 headerBackground 组件。
  • 添加选项以选择启用/禁用在过渡期间可见的堆叠卡片叠加层和阴影:cardShadowEnabled 默认为 truecardOverlayEnabled 默认为 false
  • 从 react-navigation-stack 和 react-navigation-drawer 导出 StackGestureContextDrawerGestureContext,因此您可以将相应手势的 ref 与其他手势处理程序一起使用(例如:GestureInteraction.js)。
  • 标签导航器支持 tabBarOnLongPress 配置选项,该选项默认为与标签按下事件相同。

各种修复和改进

  • 堆叠过渡性能大大提高,方法是从整个卡片中删除阴影,并仅在需要它的切片上渲染它。卡片不透明度也不再直接动画化,而是顶部放置了一个叠加层以产生类似的效果,但具有更好的性能。
  • 修复了堆叠的长期存在的问题,这些问题导致在某些模式下快速导航时静默地重新挂载屏幕:react-navigation/issues/4155
  • 支持模态框中的反向手势。
  • 堆叠卡片手势使用 react-native-gesture-handler 和原生驱动程序,因此手势在 UI 线程上运行(除非手势结束,否则它会回调到 JS)。
  • 修复了抽屉导航器的各种问题,包括围绕嵌套的问题 (react-navigation/issues/4154) 和触发打开/关闭的错误 (例如:react-navigation/react-navigation/issues/5146)。
  • 修复标签页和堆叠后退按钮的辅助功能旁白。

生态系统和 Web 支持

React Navigation 3.0 为 React Navigation 生态系统带来了一些重要更改:该项目现在跨越多个仓库和包,我们即将推出一个令人兴奋的新过渡器,并且核心终于对客户端和服务器上的 Web 应用程序提供了一流的支持!

独立项目

React Navigation 一直是一组松散耦合的导航组件:Stack、Tabs、Drawer 等。但直到现在,它们一直位于主导航仓库中,这很难维护。人们经常难以使用这些组件的不同版本,或者他们想为自己的应用程序 fork 它们。

在 v3 中,我们所有的主要包和仓库都已分离。我们的新 NPM 组织中有以下核心包

  • @react-navigation/core - 定义我们模式的原语和实用程序,以及多个路由器
  • @react-navigation/native - React Native 应用上的导航器容器和支持。主 react-navigation 包中的 createAppContainer 实际上来自此包。
  • @react-navigation/web - Web 浏览器应用容器,以及用于服务器渲染的实用程序

此外,我们已将社区维护的组件发布为独立仓库和包

  • react-navigation-stack
  • react-navigation-tabs
  • react-navigation-drawer
  • react-navigation-transitioner
  • react-navigation-hooks

为了尽可能简化体验,react-navigation 包将继续得到支持,并将包含大部分上述组件,与以前一样。

Web 支持

现在 React Navigation 的核心可以在 React Native 之外使用,我们可以为任何在 Web 上使用 React.js 的人提供一流的 Web 支持,包括那些不想使用 react-native-web 的任何人。

这是一个示例 Web 应用,演示了新的 createBrowserApp 容器和内置的 Link 组件

import { createSwitchNavigator } from "@react-navigation/core";
import { createBrowserApp, Link } from "@react-navigation/web";

class Home extends React.Component {
static path = "";
static navigationOptions = {
title: "Home",
};
render () {
return (
<div>
<h2>Home Screen</h2>
<Link toRoute="Profile" params={{ name: "Brent", view: "photos" }}>
Brent's photos
</Link>
</div>
);
}
}
class Profile extends React.Component {
static path = "/profile/:name";
...
}

const AppNavigator = createSwitchNavigator({
Home,
Profile,
});

const App = createBrowserApp(AppNavigator);

export default App;

上面的 Link 标签将渲染为:<a href="/profile/Brent?view=photos">Brent's Photos</a>

查看使用 Create React App 的简单 Web 应用 here。或者查看 这个 razzle 应用,了解包括服务器渲染在内的更复杂示例。


感谢阅读,请将您遇到的任何问题发布到 react-navigation/issues