React Navigation 入门(四)

来源:互联网 发布:sql图书馆数据库设计 编辑:程序博客网 时间:2024/06/05 14:25

RN 版本:0.50
操作环境:Windows 10
React Navigation 版本:1.0.0-beta.20

文章同步自简书:http://www.jianshu.com/p/6d178490b164

之前已经说过,每个在 navigator 中注册过的页面都会接受一个 navigation 属性,它包含以下几属性:

  • navigate - (helper) 连接其他页面
  • state - 页面当前的状态/路由
  • setParams - (helper) 更新路由的参数
  • goBack - (helper) 关闭当前活动页面并返回
  • dispatch - 给路由器发送指令行为

在之前的几篇文章中,我们已经接触过 navigate (用来跳转页面)、state(用来获取传递的参数)和 setParams(用来改变参数),这篇文章将会对它们进行更详细的说明。

注意:navigation 属性被传递给了每一个导航相关组件并且包括导航器。不过需要注意的不同点是导航器 navigator 的 navigation 属性不会包含那些 helper 类的函数(navigate, goBack 等),它只有 statedispatch 属性。如果你想要使用导航器 navigation 属性中的 navigate 函数,你必须使用 dispatch 来传递一个导航操作意图(关于 Navigation Actions 下一篇文章会讲)。

与 Redux 集成时的注意事项

注:这段文字直接翻译自官方文档,由于我还没有了解过 redux,所以看得不是太懂。有兴趣的可以看看 原文。

由于许多人对 navigator 顶级 API 的理解错误,他们并不能很好地正确使用 navigation 属性与 redux 的关联。导航器 navigator 如果没有接收到 navigation 属性话它会保持自己的状态,但这个并不是你通常情况下关联 redux 时想要的特征。对于嵌套在主导航器里面的各个导航器,你总是会想把 navigation 属性传递下去。这就允许你的顶级导航器去传达并给子导航器提供状态。这个时候你只需要将顶级路由与 redux 集成,因为其他的路由都被包含在了它的里面。

在 app 中跳转其它页面时调用的方法。它有如下参数:

navigate(routeName, params, action)

  • routeName - 在你的 app 中已经注册过的打算跳转的目的路由名称
  • params - 传给目的路由的参数
  • action - (高级)如果屏幕是导航器,则在子路由中运行的操作。有关支持的操作的完整列表,请参阅 操作文档,暂时打算下一篇文章再介绍。
class HomeScreen extends React.Component {  render() {    const {navigate} = this.props.navigation;    return (      <View>        <Text>This is the home screen of the app</Text>        <Button          // 跳转到 Profile 页面并传递参数 name          onPress={() => navigate('Profile', {name: 'Brent'})}          title="Go to Brent's profile"        />      </View>     )   }}

state - 屏幕当前状态/路由

一个屏幕可以通过 this.props.navigation.state 获取它的路由,它返回的是一个如下类型的对象:

{  // the name of the route config in the router  // 路由器中设置的路由名称  routeName: 'Profile',  // a unique identifier used to sort routes  // 为方便管理路由而产生的唯一标识  key: 'main0',  // an optional object of string options for this screen  // 给当前屏幕可供选择的参数对象  params: { hello: 'world' }}
class ProfileScreen extends React.Component {  render() {    const {state} = this.props.navigation;    // state.routeName === 'Profile'    return (      // 获取参数 name,我们之前已经见到过这种用法了      <Text>Name: {state.params.name}</Text>    );  }}

setParams - 改变路由参数

触发 setParams 方法允许页面改变路由中的参数,这对于更新头部标题及按钮很有用处。上一篇文章中我们曾经介绍过这个方法。

class ProfileScreen extends React.Component {  render() {    const {setParams} = this.props.navigation;    return (      <Button        onPress={() => setParams({name: 'Lucy'})}        title="Set title name to 'Lucy'"      />     )   }}

goBack - 关闭当前活动页面并返回

给该方法提供一个 key,来决定要从哪个路由返回(即要关闭哪个页面)。默认情况下,会关闭掉调用该方法的当前路由。如果目标是想要回到 anywhere 而不具体地说明要关闭哪个页面,可以调用 goBack(null)

class HomeScreen extends React.Component {  render() {    const {goBack} = this.props.navigation;    return (      <View>        <Button          // 关闭当前的 HomeScreen          onPress={() => goBack()}          title="Go back from this HomeScreen"        />        <Button          // 这里测试的结果也是关闭了当前的 HomeScreen          onPress={() => goBack(null)}          title="Go back anywhere"        />        <Button          // 关闭从 'screen-123' 到栈顶的所有路由          onPress={() => goBack('screen-123')}          title="Go back from screen-123"        />      </View>     )   }}

从指定的页面返回

假设我们有四个路由 A B C D 依次入栈:

navigation.navigate(SCREEN_KEY_A);...navigation.navigate(SCREEN_KEY_B);...navigation.navigate(SCREEN_KEY_C);...navigation.navigate(SCREEN_KEY_D);

假如你在 screen D 并且想要返回到 screen A(关闭 D, C 和 B),那么你就需要这么写:

// will go to screen A FROM screen Bnavigation.goBack(SCREEN_KEY_B) 

注意:这个方法里面的 key 值,并不是定义 navigator 时我们给页面自定义的 key,而是上面 state 里面的 state.key。并且我们在 D 中不能直接通过 this.props.navigation.state.key 来获取,因为它获取的是 D 的 key,所以我们要在 B 中获取到它,然后一级一级的传递给 D,最后调用 navigation.goBack(SCREEN_KEY_B) 来回到 A。

做了一个效果图

dispatch - 给路由发送一个行为

使用 dispatch 给路由指派任意的 navigation 行为,其它的 navigation 函数使用后台的 dispatch 来实现。记住如果你想指派 react-navigation 行为的话,你应该使用库里提供的 action creators。查看 Navigation Actions 来获取完整的可指派行为(具体行为会在下一篇文章进行说明)。

import { NavigationActions } from 'react-navigation'const navigateAction = NavigationActions.navigate({  routeName: 'Profile',  params: {},  // navigate can have a nested navigate action that will be run inside the child router  // navigate 可以嵌套 navigate action,它会在子路由里面执行  action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})})this.props.navigation.dispatch(navigateAction)
原创粉丝点击