原文連接:http://www.devio.org/2018/05/15/navigator-to-react-navigation/
一、什么是導航器?
導航器也可以看成一個是普通的React組件,你可以通過導航器來定義你的App的導航結構。 導航器還可以渲染通用元素,例如可以配置的標題欄和選項卡欄。
在react-navigation中有以下三種類型的導航器:
- StackNavigator: 類似於普通的Navigator,屏幕上方導航欄;
- TabNavigator: 相當於iOS里面的TabBarController,屏幕下方的標簽欄;
- DrawerNavigator: 抽屜效果,側邊滑出;
注:你可以通過以上三種導航器來創建你APP,可以是其中一個也可以多個組合,這個可以根據具體的應用場景並結合每一個導航器的特性進行選擇。
兩個和導航關於概念:
Screen navigation prop(屏幕導航屬性)
:通過navigation可以完成屏幕之間的調度操作,例如打開另一個屏幕;Screen navigationOptions(屏幕導航選項)
: 通過navigationOptions可以定制導航器顯示屏幕的方式(例如:頭部標題,選項卡標簽等);
二、導航器所支持的Props
const SomeNav = StackNavigator/TabNavigator/DrawerNavigator({ // config }); <SomeNav screenProps={xxx} ref={nav => { navigation = nav; }} onNavigationStateChange=(prevState, newState, action)=>{ } />
- ref:可以通過
ref
屬性獲取到navigation
; - onNavigationStateChange(prevState, newState, action):頂級節點除了
ref
屬性之外,還接受onNavigationStateChange(prevState, newState, action)
屬性,每次當導航器所管理的state
發生改變時,都會回調該方法;- prevState:變化之前的state;
- newState:新的state;
- 導致state變化的action;
- screenProps:向子屏幕傳遞額外的數據,子屏幕可以通過this.props.screenProps獲取到該數據。
三、Screen Navigation Prop(屏幕的navigation Prop)
當導航器中的屏幕被打開時,它會收到一個navigation
prop,navigation
prop是整個導航環節的關鍵一員,接下來就詳細講解一下navigation
的作用。
navigation包含一下功能:
- navigate:跳轉到其他界面;
- state:屏幕的當前state;
- setParams:改變路由的params;
- goBack:關閉當前屏幕;
- dispatch:向路由發送一個action;
注意:一個navigation有可能沒有navigate、setParams以及goBack,只有state與dispatch,所以在使用navigate時要進行判斷,如果沒有navigate可以使用navigation去dispatch一個新的action。如
const {navigation,theme,selectedTab}=this.props; const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'HomePage', params:{ theme:theme, selectedTab:selectedTab }, }) ] }) navigation.dispatch(resetAction)
四、使用navigate進行界面之間的跳轉
- navigate(routeName, params, action)
- routeName:要跳轉到的界面的路由名,也就是在導航其中配置的路由名;
- params:要傳遞給下一個界面的參數;
- action:如果該界面是一個navigator的話,將運行這個sub-action。
export const AppStackNavigator = StackNavigator({ HomeScreen: { screen: HomeScreen }, Page1: { screen: Page1 }) class HomeScreen extends React.Component { render() { const {navigate} = this.props.navigation; return ( <View> <Text>This is HomeScreen</Text> <Button onPress={() => navigate('Page1', {name: 'Devio'})} title="Go to Page1" /> </View> ) } }
五、使用state的params
可以通過this.props.state.params來獲取通過setParams()
,或navigation.navigate()
傳遞的參數。
<Button title={params.mode === 'edit' ? '保存' : '編輯'} onPress={() => setParams({mode: params.mode === 'edit' ? '' : 'edit'})} /> <Button title="Go To Page1" onPress={() => { navigation.navigate('Page1',{ name: 'Devio' }); }} /> const {navigation} = this.props; const {state, setParams} = navigation; const {params} = state; const showText = params.mode === 'edit' ? '正在編輯' : '編輯完成';
六、使用setParams 改變route params
setParams: function setParams(params)
: 我們可以借助setParams
來改變route params,比如,通過setParams
來更新頁面頂部的標題,返回按鈕等;
class ProfileScreen extends React.Component { render() { const {setParams} = this.props.navigation; return ( <Button onPress={() => setParams({name: 'Lucy'})} title="Set title name to 'Lucy'" /> ) }
注意navigation.setParams改變的是當前頁面的Params,如果要改變其他頁面的Params可以通過NavigationActions.setParams完成,下文會講到。
七、使用goBack返回到上一頁面或指定頁面
goBack: function goBack(key)
:我們可以借助goBack
返回到上一頁或者路由棧的指定頁面。- 其中
key
表示你要返回到頁面的頁面標識如id-1517035332238-4
,不是routeName。 - 可以通過指定頁面的
navigation.state.key
來獲得頁面的標識。 - key非必傳,也可傳null。
navigation.state {params: {…}, key: "id-1517035332238-4", routeName: "Page1"}
- 其中
export default class Page1 extends React.Component { render() { const {navigation} = this.props; return <View style=> <Text style={styles.text}>歡迎來到Page1</Text> <Button title="Go Back" onPress={() => { navigation.goBack(); }} /> </View> } }
八、通過dispatch發送一個action
dispatch: function dispatch(action)
:給當前界面設置action,會替換原來的跳轉,回退等事件。
const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'HomePage', params:{ theme:theme, selectedTab:selectedTab }, }) ] }) navigation.dispatch(resetAction)
九、NavigationActions
- Navigate : 導航到其他的頁面;
- Reset : 重置當前 state 到一個新的state;
- Back : 返回到上一個頁面;
- Set Params : 設置指定頁面的Params;
- Init : 初始化一個 state 如果 state 是 undefined;
十、Navigate:
Navigatie action會使用Navigate action的結果來更新當前的state。
- routeName:字符串,必選項,在app的router里注冊的導航目的地的routeName。
- params:對象,可選項,融合進目的地route的參數。
- actions:對象,可選項(高級),如果screen也是一個navigator,次級action可以在子router中運行。在文檔中描述的任何actions都可以作為次級action。
import { NavigationActions } from 'react-navigation' const navigateAction = NavigationActions.navigate({ routeName: 'Profile', params: {}, action: NavigationActions.navigate({ routeName: 'SubProfileRoute'}) }) this.props.navigation.dispatch(navigateAction)
十一、Reset:
Reset action刪掉所有的navigation state並且使用這個actions的結果來代替。
- index,number,必選,navigation state中route數組中激活route的index。
- actions,array,必選項,Navigation Actions數組,將會替代navigation state。
import { NavigationActions } from 'react-navigation' const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'Profile'}) ] }) this.props.navigation.dispatch(resetAction)
使用場景比如進入APP首頁后的splash頁不在使用,這時可以使用NavigationActions.reset
重置它。
index參數被用來定制化當前激活的route。舉個例子:使用兩個routes WelcomePage和HomePage給一個基礎的stack navigation設置。為了重置route到HomePage,但是在堆棧中又存放在WelcomePage之上,你可以這么做:
const resetAction = NavigationActions.reset({ index: 1, actions: [ NavigationActions.navigate({ routeName: 'WelcomePage'}), NavigationActions.navigate({ routeName: 'HomePage'}) ] }); this.props.navigation.dispatch(resetAction);
十二、Back
返回到前一個screen並且關閉當前screen.backaction creator接受一個可選的參數:
- key:這個可以和上文中講到的goBack的key是一個概念;
import { NavigationActions } from 'react-navigation' const backAction = NavigationActions.back(); this.props.navigation.dispatch(backAction);
十三、SetParams
通過SetParams我們可以修改指定頁面的Params。
- params:對象,必選參數,將會被合並到已經存在頁面的Params中。
- key:字符串,必選參數,頁面的key。
import { NavigationActions } from 'react-navigation' const setParamsAction = NavigationActions.setParams({ params: { title: 'HomePage' }, key: 'id-1517035332238-4', });
navigation中有setParams為什么還要有NavigationActions.setParams?
- 在上文中講到過navigation中有可能只有state與dispatch,這個時候如果要修改頁面的Params,則只能通過
NavigationActions.setParams
了; - 另外,navigation.setParams只能修改當前頁面的Params,而
NavigationActions.setParams
可以修改所有頁面的Params;
十四、還有那些應用場景?
1、在導航器屏幕之外使用導航功能(巧用導航器的ref)
有一種場景:有的時候我們需要在導航器中所定義的屏幕之外使用導航器來做頁面跳轉。
- 屏幕之間的跳轉是需要借助
navigation
來完成的; - 我們知道導航器中定義的屏幕可以通過
const {navigation} = this.props;
來獲取navigation
; - 那么,如果我們在非導航器中所定義的屏幕中做屏幕跳轉的關鍵一步,就是要想法獲取
navigation
; - 那么,如何才能在非導航器中所定義的屏幕中獲取到這個
navigation
呢?
import { NavigationActions } from 'react-navigation'; const AppNavigator = StackNavigator(SomeAppRouteConfigs); class App extends React.Component { someEvent() { // call navigate for AppNavigator here: this. navigation && this. navigation.dispatch( NavigationActions.navigate({ routeName: someRouteName }) ); } render() { return ( <AppNavigator ref={nav => { navigation = nav; }} /> ); } }
上述代碼通過導航器的頂級節點的ref
屬性獲取到navigation
,當上述代碼的AppNavigator
節點被渲染時,ref會被回調這是就可以獲取到navigation
了,需要提醒大家的是,這種用法對除StackNavigator
之外的其他兩種類型的導航器也是實用的哦;