Navigator
已经被React Native废弃了。也许你能够在另外的一个依赖库里react-native-deprecated-custom-components
里找到。不过既然官方推荐的是react-navigation
那咱们就来看看这个东西到底有什么好的,值不值得用。javascript
一句话归纳的话,react-navigation
很是值得用。以前配置一个Navigator
很是的繁琐,可是使用react-navigation
的任何一个导航组件都很是简单。项目的github地址在这里。java
react-navigation
包括下面三个Navigator:react
StackNavigator
: 这个组件是用来代替以前的Navigator
的。凡是维持一种“先进后厨”的栈式导航的话就能够用这个。TabNavigator
:这个组件和iOS的`TabBarController。看起来是这样的。DrawerNavigator
:这个组件就是抽屉式的导航菜单。在React Native里只有Android才有:DrawerLayoutAndroid
,在iOS里是没有的。有了DrawerNavigator
,两个平台均可以用了。我会在下文里主要介绍StackNavigator
和DrawerNavigator
。对于TabNavigatgor
它的使用很是简单,当你回了前面的两种的时候你就天然能够搞定它了。git
在github
react-native init AwesomeProject
命令后生成的默认项目里,查看index.js文件:npm
import { AppRegistry } from 'react-native'; import App from './App'; AppRegistry.registerComponent('AwesomeProject', () => App);
APP开始执行后运行的就是App
组件。也就是App.js文件export的是什么组件,App就运行什么组件。react-native
在App.js文件中,去掉export default
。就如咱们的demo作的同样,添加一个MessageContainer.js文件,并添加demo中的内容。这样在其中咱们已经有了App
、MessageContainer
两个组件。flex
下面看下如何配置。this
最简单的:code
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
。
TouchableOpacity
组件。由于按钮在iOS上还好,可是在Android上就是一个明晃晃的按钮啊,各类边框和阴影。在MessageContainer
的导航栏上就只须要一个“返回”按钮,因此只有一个headerLeft
就足够了。在首页上的导航栏的headerLeft
是用来触发稍后讲到的DrawerNavigator
的。
这样,这个靠谱的导航就完成了。
DrawerNavigator
和StackNavigator
的配置很相似。
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传递了进去。
这样咱们想要的抽屉式菜单就实现了。
如今把这两个组件结合在一块儿使用。在首页上的导航栏里的两个按钮,左侧的开启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交互中也并非只有导航到某一页,而后再从那一页跳转回来这么简单。后面有机会会讲到这方面的内容。