React Navigation——在头部菜单中使用组件方法

React Native 开发中,路由的跳转不再是 Web 世界里面的常用的 React Router,而是 React Navigation

今天介绍一下在 React Navigation 中如何在头部 (header) 调用 React 组件中的方法。

Navigator——导航器

React Navigation 可以创建多种Navigator(导航器),有通过页签控制页面跳转的TabNagivator(页签导航器),还有通过侧边栏进行页面跳转的DrawerNavigator(抽屉导航器),但最为常用的导航器是StackNavigator(堆栈导航器),它控制着普通页面之间的跳转。

StackNavigatornavigationOptions(导航配置项)中,可以设置页面的Header信息,包括头部中的标题,标题的样式,头部左半部分和头部的右半部分等。

页面头部的左半部分一般是返回按钮,而右半部分一般用来展示一些额外操作,比如保存或者下一步等,以微信的朋友圈页面为例,请见下图:

问题描述

NavigatornavigationOptions一般作为页面组件的静态属性存在,而在静态属性中没办法直接调用组件中的方法,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo extends React.Component {
  static navigationOptions = ({ navigation }) => {
    return {
      headerMode: 'screen',
      headerTitle: 'Foo',
      headerLeft: <Button onClick={() => navigation.goBack()}>Back</Button>,
      headerRight: <Button onClick={/*这里需要调用组件里的 doSomething 方法*/}>Save</Button>,
    };
  };

  doSomething = () => {
    this.setState({ count: this.state.count + 1 });
  }
  ...
}

示例代码中页面的headerModescreen,表示页面会附加一个 header,这个 header 与页面是同时存在或消失。

headerLeft表示左边的返回按钮,可以调用方法参数navigationgoBack方法返回到上一页。

而在headerRight需要调用组件中的doSomething方法,但因为navigationOptions是静态属性,所以没办法通过this关键字来得到doSomething方法,那么我们要怎么做才可以调用组件里面的方法呢?

解决思路

我们先来看下navigationOptions的方法参数navigation对象,看看这个对象里面有哪些东西可以帮到我们,下面列举了该对象几个主要的属性:

  • navigate:方法,可以跳转到其他页面
  • goBack:方法,返回上一页
  • state – 对象,包含了当前路由的名称,key 值和路由参数的一个对象
  • setParams – 方法,在路由中设置传递参数
  • getParam – 方法,在路由中获取参数

我们看到state属性包含了路由参数,而setParams方法可以设置路由参数,那么只要我们将组件中的方法通过setParams设置到路由参数里面,然后在state中就可以获取到组件的方法了。

还有一个问题,我们在什么时候将组件方法设置到路由参数里面比较好呢?在几个 React 生命周期方法中,componentWillMountcomponentDidMount都适合做这件事,但componentWillMount方法 React 官方已不推荐使用,所以我们这里用componentDidMount

实现方法

我们在之前的代码上做一下扩展:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Foo extends React.Component {
  static navigationOptions = ({ navigation }) => {
    // state 里面的 params 已经包含了组件的 doSomething 方法,所以可以直接获取
    const { doSomething } = navigation.state.params;
    return {
      headerMode: 'screen',
      headerTitle: 'Foo',
      headerLeft: <Button onClick={() => navigation.goBack()}>Back</Button>,
      headerRight: <Button onClick={doSomething}>Save</Button>,
    };
  };

  componentDidMount() {
    // 只要是`StackNavigator`都可以通过`this.props`来获取到`navigation`对象
    this.props.navigation.setParams({ doSomething: this.doSomething });
  }

  doSomething = () => {
    this.setState({ count: this.state.count + 1 });
  }
  ...
}

我们在componentDidMount中将doSomething方法设置到路由参数中,然后在navigationOptions中通过navigation.state.params就可以获取到该方法了,也可以通过navigation.getParam方法来获取路由参数。

总结

React Navigation 是 React Native 开发中的一个重要角色,而且最近也升级到了 2.0,很多功能特性都得到了增强和改善。这里只是介绍了开发过程中遇到的一个小坑,希望能对遇到同样问题的同学有所帮助。

参考链接

赞赏

如果文章对您有所帮助,可以捐赠我喝杯咖啡😌,捐赠方式:

BTC 地址: 3LYgSyf7ddMALwGWPQr3PY4wzjsTDdg1oV
ETH 地址: 0x0C9b27c89A61aadb0aEC24CA8949910Cbf77Aa73
qrcode

Comments