react-navigation介绍

作用:

使用react-navigation来实现各个界面的跳转和不同板块的切换。

react-navigation主要包括三个组件:

  • StackNavigator 导航组件
  • TabNavigator 切换组件
  • DrawerNavigator 抽屉组件

StackNavigator -用于实现各个页面之间的跳转: 一次只渲染一个页面,并提供页面之间跳转的方法。 当打开一个新的页面时,它被放置在堆栈的顶部

TabNavigator - 渲染一个选项卡,让用户可以在几个页面之间切换

DrawerNavigator - 提供一个从屏幕左侧滑入的抽屉效果

安装

yarn add @react-navigation/native
或
npm install @react-navigation/native

安装依赖关系
在项目的路径下,执行下面的依赖命令

yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

如果是mac环境

npx pod-install ios

react-native-screens包需要一个额外的配置步骤才能在Android设备上正常工作。编辑MainActivity.java文件,它位于android/app/src/main/java/<你的包名>/MainActivity.java

MainActivity 文件里面添加下面代码:

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(null);
}

并确保在文件的顶部添加一个import语句:

import android.os.Bundle;

NavigationContainer 包装应用程序

把整个应用包装在NavigationContainer中。通常会在你的入口文件中这样做,比如index.js或App.js:

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';export default function App() {return (<NavigationContainer>{/* Rest of your app code */}</NavigationContainer>);
}

在一个典型的React Native应用中,NavigationContainer应该只在应用的根目录中使用一次,不应该嵌套多个navigationcontainer。

react-navigation/stack介绍

在web浏览器中,您可以使用锚(<a>标签)链接到不同的页面。当用户单击链接时,URL被推送到浏览器历史堆栈。当用户按下后退按钮时,浏览器会从历史堆栈的顶部弹出该项,因此活动页面现在是以前访问过的页面。React Native不像web浏览器那样有一个内置的全局历史堆栈的想法——这是React Navigation进入故事的地方。

react-navigation的stack(堆栈导航器)提供了在屏幕之间切换和管理导航历史的方法。当用户在应用程序上交互时,应用程序从堆栈中推送和弹出项目,可以使用户看到不通的屏幕。与web浏览器的区别,它提供了在Android和ios中在栈中路由之间导航时所期望的手势和动画。

我们上面安装的库是导航器的构建块和共享基础,React Navigation中的每个导航器都有自己的库。要使用堆栈导航器,我们需要安装@react-navigation/native-stack:

安装navigator库

npm install @react-navigation/native-stack
yarn add @react-navigation/native-stack

创建导航器

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

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

例子

// In App.js in a new projectimport * 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;

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

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

Stack.Screen必须配置的有名称和组件。

配置导航器

例子

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 属性,前者对应于我们导航的路由名称,后者对应于它要渲染的组件名称。

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

Screen 的component属性接受的是组件,而不是函数。不要传递内联函数(例如component={() => <HomeScreen />}),否则当父组件重新渲染时,你的组件将卸载并重新加载,失去所有状态。

options

stack中的每个Screen组件都可以为导航器指定一些选项,例如在头部中呈现的标题。这些属性可以被传递到每个Screen组件的options属性中:

例子

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

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

添加多个props

有时我们可能想要将很多属性传递给屏幕。我们可以通过两种方法做到这一点:

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

2.使用回调函数,传递多个props

例子

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

总结:

1.React Native 不能像web浏览器那样有一个内置的导航API。React Navigation提供了这个功能,以及实现了IOS和Android的手势和动画来在屏幕之间切换。

2.Stack.Navigator是一个组件,路由配置为它的子组件,所有路由常用的配置选项可以用screenOptions属性配置

3.每个Stack.Screen组件都必须有一个name属性,一个component属性指定路由。

4.指定堆栈的初始路由,需要使用initialRouteName

屏幕切换

在上一节,我们定义了两个路由Home和Details,但是还没有学习如何从Home到Details.

如果在Web浏览器中,我们会这样写:

<a href="details.html">Go to Details</a>

或者下面的写法:

<aonClick={() => {window.location.href = 'details.html';}}
>Go to Details
</a>

我们将执行与后者类似的操作,但不是使用window.location。

导航到新屏幕

例子

import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';function HomeScreen({ navigation }) {return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Home Screen</Text><Buttontitle="Go to Details"onPress={() => navigation.navigate('Details')}/></View>);
}// ... other code from the previous section

navigation - navigation属性将被传递给堆栈中的每一个组件;

navigate('Details') - 用户要移动到的路由

多次导航到一个路由

function DetailsScreen({ navigation }) {return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Details Screen</Text><Buttontitle="Go to Details... again"onPress={() => navigation.navigate('Details')}/></View>);
}

如果已经在当前路由上,再次跳转到这个路由,将什么都不会做。

有时我们需要跳转到另一个Detail屏幕,需要向每个路由传递一些唯一的数据。我们可以用push更改导航。

<Buttontitle="Go to Details... again"onPress={() => navigation.push('Details')}
/>

每次调用push时,我们都会向导航堆栈添加一个新路由。当你调用navigate时,它首先会尝试找到一个具有该名称的现有路由,并且只有在堆栈中还没有路由的情况下才会推送一个新的路由。

回到上一个路由

有时我们需要回到上一个页面,需要使用 navigation.goBack()

例子

function DetailsScreen({ navigation }) {return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Details Screen</Text><Buttontitle="Go to Details... again"onPress={() => navigation.push('Details')}/><Button title="Go to Home" onPress={() => navigation.navigate('Home')} /><Button title="Go back" onPress={() => navigation.goBack()} /></View>);
}

在Android上,React Navigation与硬件后退按钮挂钩,并在用户按下后退按钮时为你触发goBack()函数,因此它的行为与用户期望的一样。

另一个常见的需求是能够返回多个屏幕 — 有多个屏幕,你希望返回到第一个屏幕,可以使用navigate(‘Home’),另一种方式是navigation.popToTop(),它会返回到堆栈中的第一个屏幕。

例子

function DetailsScreen({ navigation }) {return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Details Screen</Text><Buttontitle="Go to Details... again"onPress={() => navigation.push('Details')}/><Button title="Go to Home" onPress={() => navigation.navigate('Home')} /><Button title="Go back" onPress={() => navigation.goBack()} /><Buttontitle="Go back to first screen in stack"onPress={() => navigation.popToTop()}/></View>);
}

总结:

1.navigation.navigate(‘RouteName’)如果路由还未在堆栈中,则将其推送到本机堆栈导航器,否则将跳转到该屏幕。

2.我们可以任意调用navigation.push(‘RouteName’),它会继续推送路由。

3.标题栏将自动显示一个后退按钮,但是您可以通过调用navigation.goBack()以编程的方式返回。在安卓系统上,硬件返回按钮的工作原理和预期一样。

4.你可以使用navigation.navigate(‘RouteName’)返回堆栈中的一个现有屏幕,也可以使用navigation.popToTop()返回堆栈中的第一个屏幕。

5.navigation属性可用于所有屏幕组件(在路由配置中定义为Screen的组件,并由React navigation作为路由呈现)。

向路由传递参数

现在我们已经知道了如何创建带有一些路由的堆栈导航器,并在这些路由之间导航,让我们看看在跳转路由时,如何将数据传递给下一个组件。

这里有两个部分:

1.通过将参数放入一个对象中,对象作为navigation.navigate的第二个参数

navigation.navigate('RouteName', { /* params go here */ })

2.在跳转到的Screen组件中读取params获得参数 :route.params

我们建议您传递的参数是json序列化的。

例子

function HomeScreen({ navigation }) {return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Home Screen</Text><Buttontitle="Go to Details"onPress={() => {/* 1. Navigate to the Details route with params */navigation.navigate('Details', {itemId: 86,otherParam: 'anything you want here',});}}/></View>);
}function DetailsScreen({ route, navigation }) {/* 2. Get the param */const { itemId, otherParam } = route.params;return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Details Screen</Text><Text>itemId: {JSON.stringify(itemId)}</Text><Text>otherParam: {JSON.stringify(otherParam)}</Text><Buttontitle="Go to Details... again"onPress={() =>navigation.push('Details', {itemId: Math.floor(Math.random() * 100),})}/><Button title="Go to Home" onPress={() => navigation.navigate('Home')} /><Button title="Go back" onPress={() => navigation.goBack()} /></View>);
}

更新参数

Screen也可以更新他们的参数,使用navigation.setParams方法

navigation.setParams({query: 'someText',
});

避免使用setParams来更新屏幕选项,如标题等。如果需要更新选项,请使用setOptions。

初始参数

你可以向Screen传递一些初始参数。如果导航到此屏幕时没有指定任何参数,则将使用初始参数。它们还与您传递的任何参数浅层合并。初始参数可以用initialParams属性来指定:

<Stack.Screenname="Details"component={DetailsScreen}initialParams={{ itemId: 42 }}
/>

向上一个屏幕传递参数

参数不仅向新屏幕传递一些数据有用,而且向前一个屏幕传递数据也有用。例如,假设您有一个带有“创建发布”按钮的屏幕,“创建发布”按钮打开一个新屏幕来创建一个帖子。创建之后,您希望将提交的数据传递回上一个屏幕。

为此,可以使用navigate方法,如果屏幕已经存在,它的作用类似于goBack。你可以通过导航传递参数来传递回数据:

例子

function HomeScreen({ navigation, route }) {React.useEffect(() => {if (route.params?.post) {// Post updated, do something with `route.params.post`// For example, send the post to the server}}, [route.params?.post]);return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Buttontitle="Create post"onPress={() => navigation.navigate('CreatePost')}/><Text style={{ margin: 10 }}>Post: {route.params?.post}</Text></View>);
}function CreatePostScreen({ navigation, route }) {const [postText, setPostText] = React.useState('');return (<><TextInputmultilineplaceholder="What's on your mind?"style={{ height: 200, padding: 10, backgroundColor: 'white' }}value={postText}onChangeText={setPostText}/><Buttontitle="Done"onPress={() => {// Pass and merge params back to home screennavigation.navigate({name: 'Home',params: { post: postText },merge: true,});}}/></>);
}

在这里,你按“Done”后,home页面的参数将被更新。

向嵌套导航器传递参数

如果有嵌套的导航器,传递参数的方式就有点不同了。例如,假设您在一个导航器有一个Account页面,希望将参数传递Settings页面。然后你可以像下面这样传递参数:

navigation.navigate('Account', {screen: 'Settings',params: { user: 'jane' },
});

哪些参数在params中

params就像屏幕的选项,他们应该只包含屏幕显示内容的信息。应该避免传递屏幕的完成数据(例如,一个页面显示用户信息,应该传递用户id而不是用户对象)。还要避免传递多个屏幕使用的数据,这样的数据应该放在全局存储中。

// Don't do this
navigation.navigate('Profile', {user: {id: 'jane',firstName: 'Jane',lastName: 'Done',age: 25,},
});

这看起来很方便,并且允许您使用route.params.user访问用户对象,而无需任何额外的工作。

然而,这是一种反模式。像用户对象这样的数据应该在全局存储中,而不是在导航状态中。否则,您将在多个地方复制相同的数据。这可能会导致错误,例如,即使用户对象在导航后发生了更改,配置文件屏幕也会显示过时的数据。

可能会出现以下问题:

1.URL是屏幕的表示,所以它也需要包含参数,即完整的用户对象,这可能会使URL非常长和不可读

2.因为用户对象在URL中,所以可能会传递一个随机的用户对象,表示一个不存在的用户,或者配置文件中有不正确的数据

3.如果没有传递用户对象,或者格式化不正确,这可能会导致崩溃,因为屏幕不知道如何处理它

更好的方法是只在参数中传递用户的ID:

navigation.navigate('Profile', { userId: 'jane' });

现在,可以使用传递的userId从全局存储中获取用户。这消除了许多问题,比如过时的数据或有问题的url。

一些应该在params中的例子:

1.id,如用户id,项目id等,例如navigation.navigate('Profile', { userId: 'Jane' })

2.当你有一个项目列表时,用于排序、过滤数据等的参数,例如navigation.navigate('Feeds', { sortBy: 'latest' })

3.用于分页的时间戳、页码或游标,例如 navigation.navigate('Chat', { beforeTime: 1603897152675 })

4.在屏幕上输入的数据,例如,navigation.navigate('ComposeTweet', { title: 'Hello world!' })

本质上,就是传递屏幕所需的最少的参数。

总结

1.navigate和push接受可选的第二个参数,让你把数据传递给要跳转到的路由。例如,``navigation.navigate(‘RouteName’, { paramName: ‘value’ }).

2.可以通过route.params获取页面的参数

3.可以使用navigation.setParams更新屏幕的参数

4.可以使用initialParams属性在Screen上传递初始参数

5.params应该包含显示屏幕所需的最小数据

配置标题栏

设置头部title

Screen组件接受options属性,它可以是一个对象,也可以是一个返回对象的函数,该对象包含各种配置选项。我们使用的标题是title,如下面的例子所示。

例子

function StackScreen() {return (<Stack.Navigator><Stack.Screenname="Home"component={HomeScreen}options={{ title: 'My home' }}/></Stack.Navigator>);
}

在title中使用params

为了在标题中使用参数,需要在Screen的options中返回回调函数,参数有{ navigation, route } ,可以通过route获取params

例子

function StackScreen() {return (<Stack.Navigator><Stack.Screenname="Home"component={HomeScreen}options={{ title: 'My home' }}/><Stack.Screenname="Profile"component={ProfileScreen}options={({ route }) => ({ title: route.params.name })}/></Stack.Navigator>);
}

用setOptions更新options

通常需要在当前页面本身,更新本页面的options,我们可以用navigation.setOptions

/* Inside of render() of React class */
<Buttontitle="Update the title"onPress={() => navigation.setOptions({ title: 'Updated!' })}
/>

调整header样式

在自定义标题样式时,有三个关键属性可以使用:

headerStyle, headerTintColor, and headerTitleStyle.

headerStyle: 一个样式对象,它将应用于包装header的视图。如果你在上面设置了backgroundColor,那将是你的标题的颜色。

headerTintColor:后退按钮和title都使用这个属性作为它们的颜色。在下面的例子中,我们将颜色设置为白色(#fff),这样后退按钮和头部标题就会是白色。

headerTitleStyle:如果我们想为title定制fontFamily, fontWeight和其他文本样式属性,我们可以使用它来完成。

function StackScreen() {return (<Stack.Navigator><Stack.Screenname="Home"component={HomeScreen}options={{title: 'My home',headerStyle: {backgroundColor: '#f4511e',},headerTintColor: '#fff',headerTitleStyle: {fontWeight: 'bold',},}}/></Stack.Navigator>);
}

这里有几点需要注意:

1.在iOS上,状态栏文本和图标是黑色的,这在深色背景下看起来不太好。我们不会在这里讨论它,但您应该确保按照状态栏指南中的描述 配置状态栏以适应您的屏幕颜色。

2.我们设置的配置只适用于主屏幕;当我们导航到详细信息屏幕时,默认样式又回来了。现在我们来看看如何在屏幕之间共享选项。

跨页面共享opitons

通常希望在多个屏幕上,以类似的方式配置header。例如,您的公司品牌颜色可能是红色,所以您希望header的背景颜色是红色,而色调颜色是白色。

在上面运行示例中使用的颜色在Home上,当你跳转到DetailsScreen时,颜色会回到默认值。如果我们必须将选项头样式应用到每个组件,我们可以将配置移到Stack.Navigator的screenOptions属性下。

function StackScreen() {return (<Stack.NavigatorscreenOptions={{headerStyle: {backgroundColor: '#f4511e',},headerTintColor: '#fff',headerTitleStyle: {fontWeight: 'bold',},}}><Stack.Screenname="Home"component={HomeScreen}options={{ title: 'My home' }}/></Stack.Navigator>);
}

现在,任何屏幕,都将有我们精彩的品牌风格。当然,如果我们需要的话,一定有一种方法可以覆盖这些选项。

用自定义组件替换标题

有时,您需要更多的控制,而不仅仅是更改title的文本和样式——例如,您可能想要呈现一个图像来代替标题,或将标题变成一个按钮。在这些情况下,您可以完全重写用于标题的组件,并提供您自己的组件。

function LogoTitle() {return (<Imagestyle={{ width: 50, height: 50 }}source={require('@expo/snack-static/react-native-logo.png')}/>);
}function StackScreen() {return (<Stack.Navigator><Stack.Screenname="Home"component={HomeScreen}options={{ headerTitle: (props) => <LogoTitle {...props} /> }}/></Stack.Navigator>);
}

你可能想知道,为什么我们提供了一个headerTitle而不是title,就像以前一样?原因是headerTitle是一个特定于堆栈导航器的属性,headerTitle默认为一个显示标题的Text组件。

总结

1.您可以在Screen组件的options中自定义header。

2.options属性可以是对象或函数。当它是一个函数时,它被提供一个带有导航和路由参数的对象。

3.您还可以在初始化堆栈导航器配置时,指定公共的screenOptions属性。props优先于该配置。

react-navigation 6.x学习相关推荐

  1. 使用Redux在React Navigation App中管理状态

    by Andrea Bizzotto 通过安德里亚·比佐托(Andrea Bizzotto) 使用Redux在React Navigation App中管理状态 (Managing State in ...

  2. RN路由-React Navigation组件5.x-基本原理(中文文档)

    ##引言 React Native路由导航,有它就够了!该文档根据React Navigation文档翻译,有些内容会根据自己的理解进行说明,不会照搬直译,若发现理解有问题的地方,欢迎大家提点!由于本 ...

  3. React Native小白入门学习路径——五

    React Native小白入门学习路径--五 序 "哦天呐!" 这句话成了我在实验室的口头禅, 老师可能觉得我们都是大神吧,都还在看着基础就给布置了那么多任务:写一个RN的TDD ...

  4. react navigation 中使用goBack()跳转到指定页面

    一.适用场景: 在app端开发的时候,相反回到某一个页面的时候保持跳转页面的所有状态不更新,也就是说不触发新的生命周期. 例如:A-->B-->C-->D 要想从D页面直接返回到B页 ...

  5. 【react】react18的学习(三)--hooks组件

    上一篇:[react]react18的学习(二)-三种组件 1.useState:使函数组件可以使用并修改 state import { useState } from 'react' const [ ...

  6. React Navigation 基本使用

    React Navigation 基本使用 参考资料 https://reactnavigation.org/docs/ 环境搭建 Minimum requirementsreact-native & ...

  7. React Native v0.55 学习笔记1

    React Native v0.55 学习笔记1 学习内容来自官网文档0.55版本 RN 是基于 React 的思想,相比于 web 的一些组件,RN 使用的是基于原生( android.ios )的 ...

  8. React Navigation 路由导航库升级 5.x

    当前版本:3.0.0 升级版本:5.12.8 安装依赖 $ yarn add   @react-navigation/native   @react-navigation/stack   @react ...

  9. react navigation中使用goBack返回指定页面

    goBack 首先, 现在看一下react navigation官网中对goBack的描述: goBack的参数为页面的key, 这个key是系统随机分配的, 而不是手动设置的routeName, 所 ...

  10. React Native跨平台开发学习笔记

    App的分类(按开发方式) 大致可以分为这3种: native app(原生app:ios或安卓)原生应用程序 原生应用程序外观和运行起来(性能)是最佳的.可以访问本地资源,开法成本高.发布审核周期长 ...

最新文章

  1. 【青少年编程】黄羽恒:漫天飞雪
  2. HTML:Browser 对象
  3. linux内核对伙伴系统的改进--migrate_type
  4. [css] 你有用过IE css的expression表达式吗?说说你对它的理解和它有什么作用呢?
  5. spark SortShuffleWriter的实现
  6. ip动态分配痕迹会保留多久_段王爷《新国潮七剑》为你解剖新国潮还能潮多久?...
  7. SSIS 连接ORACLE 无法从 SQL 命令中提取参数的解决方案
  8. WCF之旅读书笔记(2):WCF如何通过Binding进行通信
  9. (一)网络编程基础之套接字入门
  10. boost::bind 与 boost::function 的使用方法例子
  11. 活动喵怎么用?定向寻宝活动设计思路和实操(附2019最新教程)
  12. 海康威视摄像头录制的视频无法用PR剪辑
  13. 计算机无法自动矫正时间,怎么设置电脑上的时间自动同步进行校正
  14. JavaScript中的时间与日期、正则表达式和Function类型
  15. 2018计算机考研各科试卷分值分布
  16. zonecreate
  17. HB 7066机舱内部非金属材料毒性测定
  18. web前端开发新技术,CSS介绍
  19. python 边缘扩充方式
  20. 机器学习之k-means算法详解

热门文章

  1. kubelet漏洞利用
  2. python 列表比较不同物质的吸热能力_比较不同物质吸热能力实验专项
  3. Deallocate unused
  4. 绕过kernel32自己实现WriteProcessMemory
  5. mysql my.cnf 日志_mysql中my.cnf配置项记录
  6. Diablo3手游开发日志
  7. 知乎热议程序员「35岁定律」,32岁女生转行学Java是否可行?
  8. Seve (Radio Edit) 音乐播放器 V 1.0
  9. P1095 守望者的逃离
  10. 深入理解协方差(图文详解)