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交互中也並非只有導航到某一頁,而後再從那一頁跳轉回來這麼簡單。後面有機會會講到這方面的內容。