Navigator已经被React Native废弃了。也许你可以在另外的一个依赖库里react-native-deprecated-custom-components里找到。不过既然官方推荐的是react-navigation那我们就来看看这个东西到底有什么好的,值不值得用。

一句话概括的话,react-navigation非常值得用。之前配置一个Navigator非常的繁琐,但是使用react-navigation的任何一个导航组件都非常简单。项目的github地址在这里

react-navigation包括下面三个Navigator:

  • StackNavigator: 这个组件是用来代替之前的Navigator的。凡是维持一种“先进后厨”的栈式导航的话就可以用这个。
  • TabNavigator:这个组件和iOS的`TabBarController。看起来是这样的。
  • DrawerNavigator:这个组件就是抽屉式的导航菜单。在React Native里只有Android才有:DrawerLayoutAndroid,在iOS里是没有的。有了DrawerNavigator,两个平台都可以用了。

我会在下文里主要介绍StackNavigatorDrawerNavigator。对于TabNavigatgor它的使用非常简单,当你回了前面的两种的时候你就自然可以搞定它了。

Stack Navigator

react-native init AwesomeProject

命令后生成的默认项目里,查看index.js文件:

import { AppRegistry } from 'react-native';
import App from './App'; AppRegistry.registerComponent('AwesomeProject', () => App);

APP开始执行后运行的就是App组件。也就是App.js文件export的是什么组件,App就运行什么组件。

App.js文件中,去掉export default。就如我们的demo做的一样,添加一个MessageContainer.js文件,并添加demo中的内容。这样在其中我们已经有了AppMessageContainer两个组件。

下面看下如何配置。

最简单的:

export default NavHome = StackNavigator({
Home: {
screen: NavApp,
},
Message: {
screen: MessageContainer,
},
})

导出StackNavigator方法生成的组件NavHome。运行起来之后,理论上就可以导航了。但是会有问题,因为这时还没有能够跳转的触发点。所以,我们还要做如下的修改。

修改App.js文件的内容。在其中添加一个按钮,点击之后可以进入到MessageContainer组件。修改MessageContainer.js文件,在里面添加一个按钮返回。

//App.js
<Button onPress={this.props.navigation.navigate('Message')} title={'To message'} /> //MessageContainer.js
<Button onPress={this.props.navigation.goBack()} title={'Go Back'} />

但是,这样还是demo的水平,离真正的产品级使用还差很多。一般的App,在push到下一个页面的时候会点击navigation bar的回退按钮返回上一页。我们就来实现这个功能。

使我们首先看一下StackNavigator的API:

StackNavigator(RouteConfigs, StackNavigatorConfig)

通过查看文档,要实现这个功能需要在RouteConfigs里面增加navigationOptions来达到。如下:

export default NavHome = StackNavigator({
Home: {
screen: App,
navigationOptions: ({navigation}) => ({
title: 'Home',
headerLeft: (<Button onPress={() => navigation.navigate('DrawerToggle')} title={'User'} />),
headerRight: (<Button onPress={() => navigation.navigate('Message')} title={'Message'} />),
})
},
Message: {
screen: MessageContainer,
navigationOptions: ({navigation}) => ({
title: "Message",
headerLeft: (<Button title='Back' onPress={() => {navigation.goBack();}} />)
})
},
});

详细看一下navigationOptions

  1. title:是导航栏上显示的title。
  2. headerLeft: 是导航栏左侧的组件。我这里放了一个按钮。更好的是放置一个TouchableOpacity组件。因为按钮在iOS上还好,但是在Android上就是一个明晃晃的按钮啊,各种边框和阴影。
  3. headerRight: 是导航栏右侧的组件。

MessageContainer的导航栏上就只需要一个“返回”按钮,所以只有一个headerLeft就足够了。在首页上的导航栏的headerLeft是用来触发稍后讲到的DrawerNavigator的。

这样,这个靠谱的导航就完成了。

Drawer Navigator

DrawerNavigatorStackNavigator的配置很类似。

const NavApp = DrawerNavigator({
Home: {
screen: App,
},
MyWallet: {
screen: MyWalletView,
},
MyVoucher: {
screen: MyVoucherView,
}
});

这个时候看起来是这样的:

但是我想要的效果是这样的:

显然,文档里提供的一些简单的定制是不能完成这样的效果的。于是,我们查看文档,发现有办法直接替换掉默认的Drawer实现,非常简单:

const NavApp = DrawerNavigator({
Home: {
screen: App,
},
User: {
screen: UserContainer,
},
MyWallet: {
screen: MyWalletView,
},
MyVoucher: {
screen: MyVoucherView,
}
}, {
contentComponent: props => (<UserDrawer items={props} />)
})

看下API:

DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)

只要叫上DrawerNavigatorConfig配置里的contentComponent配置。也就是上面配置的第二个参数。

{
contentComponent: props => (<UserDrawer items={props} />)
}

contentComponent就是drawer的内容组件。这里我们用的是UserDrawer组件,并把props传递了进去。

这样我们想要的抽屉式菜单就实现了。

StackNavigator和DrawerNavigator结合使用

现在把这两个组件结合在一起使用。在首页上的导航栏里的两个按钮,左侧的开启drawer导航,右侧的是“message”按钮,使用StackNavigator组件导航。

如果是在drawer导航里使用StackNavigator的话,那么只要这样配置:

export default NavHome = StackNavigator({
Home: {
screen: NavApp,
navigationOptions: ({navigation}) => ({
title: 'Home',
headerLeft: (<Button onPress={() => navigation.navigate('DrawerToggle')} title={'User'} />),
headerRight: (<Button onPress={() => navigation.navigate('Message')} title={'Message'} />),
})
},
Message: {
screen: MessageContainer,
navigationOptions: ({navigation}) => ({
title: "Message",
headerLeft: (<Button title='Back' onPress={() => {navigation.goBack();}} />)
})
},
}); export default NavApp = DrawerNavigator({
Home: {
screen: NavHome, // ***
},
MyWallet: {
screen: MyWalletView,
},
MyVoucher: {
screen: MyVoucherView,
}
}, {
contentComponent: props => (<UserDrawer items={props} />)
})

要在Drawer导航里用stack导航,那么就在drawer导航里的某个路由选项里加上screen: NavHome。这个NavHome就是stack导航。反之,则是在stack导航里的某个route选项的screen上指定drawer导航。

但是在使用上还是有一点区别的。如果drawer导航里包含stack导航。那么drawer导航菜单的最高点是在屏幕的最高点。反之,如果drawer导航被stack导航包含的话,drawer导航菜单的最高点是在导航栏的下方的。如图:

回到正题。从drawer导航菜单跳转到任何的页面后如何跳转回来呢?还是老方法:

export default class MyWalletView extends React.Component {
render() {
return (
<TouchableOpacity
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}
onPress={() => this.props.navigation.goBack()}>
<Text>{'My Wallet'}</Text>
</TouchableOpacity>
);
}
}

调用props传入的navigation的方法来实现返回:

this.props.navigation.goBack()

总结

更多请看代码吧。留下来TabNavigator来给各位读者朋友实践一下练练手吧。其实配置的简单程度比早前React Native里的Navigator已经降低了很多了。

StackNavigator里还有除了navigate()goBack()两个方法之外,还有其他的一些方法可以调用。实际的App交互中也并不是只有导航到某一页,然后再从那一页跳转回来这么简单。后面有机会会讲到这方面的内容。

React Native填坑之旅 -- 使用react-navigation代替Navigator的更多相关文章

  1. React Native填坑之旅--与Native通信之iOS篇

    终于开始新一篇的填坑之旅了.RN厉害的一个地方就是RN可以和Native组件通信.这个Native组件包括native的库和自定义视图,我们今天主要设计的内容是native库方面的只是.自定义视图的使 ...

  2. React Native填坑之旅--Flow篇(番外)

    flow不是React Native必会的技能,但是作为正式的产品开发优势很有必要掌握的技能之一.所以,算是RN填坑之旅系列的番外篇. Flow是一个静态的检查类型检查工具,设计之初的目的就是为了可以 ...

  3. React Native填坑之旅--布局篇

    代码在这里: https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller 回头看看RN ...

  4. React Native填坑之旅--组件生命周期

    这次我们来填React Native生命周期的坑.这一点非常重要,需要有一个清晰的认识.如果你了解Android或者iOS的话,你会非常熟悉我们今天要说的的内容. 基本上一个React Native的 ...

  5. React Native填坑之旅--重新认识RN

    如同黑夜里的一道光一样,就这么知道了F8. F8是每年一次Facebook每年一次的开发者大会.每次大会都会release相应的APP,iOS.Android都有.之前都是用Native开发的,但是2 ...

  6. React Native填坑之旅--Navigation篇

    React Native的导航有两种,一种是iOS和Android通用的叫做Navigator,一种是支持iOS的叫做NavigatorIOS.我们这里只讨论通用的Navigator.会了Naviga ...

  7. React Native填坑之旅--ListView篇

    列表显示数据,基本什么应用都是必须.今天就来从浅到深的看看React Native的ListView怎么使用.笔者写作的时候RN版本是0.34. 最简单的 //@flow import React f ...

  8. React Native填坑之旅--动画

    动画是提高用户体验不可缺少的一个元素.恰如其分的动画可以让用户更明确的感知当前的操作是什么. 无疑在使用React Native开发应用的时候也需要动画.这就需要知道RN都给我们提供了那些动画,和每个 ...

  9. React Native填坑之旅--Button篇

    从React过来,发现React Native(以下简称RN)居然没有Button.隔壁的iOS是有UIButton的,隔壁的隔壁的Android里也是有的.没有Button,就没有点击效果啊.这还真 ...

  10. React Native填坑之旅 -- 使用iOS原生视图(高德地图)

    在开发React Native的App的时候,你会遇到很多情况是原生的视图组件已经开发好了的.有的是系统的SDK提供的,有的是第三方试图组件,总之你的APP可以直接使用的原生视图是很多的.React ...

随机推荐

  1. 开博近一年的感想 by 程序员小白

    /* 好吧,这里的写博客应该理解为更宏观的写文章. */   在去年的这个时候,我所知道的平台只有 CSDN 和博客园..然而 CSDN 的广告实在是不想吐槽了,选择博客园是一件非常自然的事情.要说开 ...

  2. Knapsack I 竟然是贪心,证明啊。。。。

    Knapsack I Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitSt ...

  3. C# 7.0 新特性:本地方法

    C# 7.0:本地方法 VS 2017 的 C# 7.0 中引入了本地方法,本地方法是一种语法糖,允许我们在方法内定义本地方法.更加类似于函数式语言,但是,本质上还是基于面向对象实现的. 1. 本地方 ...

  4. excel表格数据导入数据库Oracle

    方法一: 1.创建数据表 CREATE TABLE T_USER (   ID             VARCHAR2(32) primary key,   NAME           VARCH ...

  5. php过滤textarea 中的换行符问题

    之前我写的替换代码是这样的 $content = str_replace('\r\n', '', $_POST['content']); 为了确保window和Linux的换行符都能去掉,改成这样的: ...

  6. SqlServer2008 导入导出txt或Execl数据

    --右键user表所在的数据库,然后任务--导出数据,然后根据提示设置就行 --从txt中导入 EXEC master..xp_cmdshell 'bcp Northwind.dbo.sysusers ...

  7. Java 线程并发

    http://www.yesky.com/9/1899009.shtml http://zhidao.baidu.com/link?url=-xZ9JLo5x4bvCSVyXb2XhO6TODnBcU ...

  8. 通过nginx的fastcgi_param来设置环境变量

    在nginx配置文件中,可以在nginx总体的配置文件nginx.conf中,也可以在单独的网站配置环境中进行设置,如:www.tomener.com.conf 在配置环境server段locatio ...

  9. 简易RPC框架-客户端限流配置

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  10. 队列(存储结构数组)--Java实现

    /*队列:其实也是一种操作受限的线性表 *特点:先进先出 *队尾指针:负责元素的进队 *队头指针:负责元素的出队 *注意:普通队--容易浪费空间,一般队列使用最多的就是循环队列--指针环绕 *队列的实 ...