隨着React Navigation逐漸穩定,Navigator也被光榮的退休了。在React Native生態環境中須要一款可擴展且易於使用的導航組件,Navigator 天然勝任不了,這時React Native社區便孕育出了一個開源導航組件React Navigation。html
React Navigation的出現替代了Navigator、 Ex-Navigation等老一代的導航組件,React Navigation能夠說是Navigator的增強版,不只有Navigator的所有功能,另外還支持底部導航相似於與iOS中的UITabBarController,此外它也支持側拉效果方式的導航相似於Android中的抽屜效果。react
這篇文章將向你們分享React Navigation3x開發的一些實用技巧,以及從navigator到React Navigation的一些實戰經驗。數組
導航器也能夠當作一個是普通的React組件,你能夠經過導航器來定義你的App的導航結構。 導航器還能夠渲染通用元素,例如能夠配置的標題欄和選項卡欄。app
在React Navigation中有如下7種類型的導航器:ide
你能夠經過以上7種導航器來建立你APP,能夠是其中一個也能夠多個組合,這個能夠根據具體的應用場景並結合每個導航器的特性進行選擇。函數
在開始學習7種導航器以前,咱們須要先了解兩個和導航關於概念:學習
Screen navigation prop(屏幕導航屬性)
:經過navigation能夠完成屏幕之間的調度操做,例如打開另外一個屏幕;Screen navigationOptions(屏幕導航選項)
: 經過navigationOptions能夠定製導航器顯示屏幕的方式(例如:頭部標題,選項卡標籤等);const SomeNav = createStackNavigator/createBottomTabNavigator/createMaterialTopTabNavigator/createDrawerNavigator/createSwitchNavigator({
// config
});
<SomeNav
screenProps={xxx}
ref={nav => { navigation = nav; }}
onNavigationStateChange=(prevState, newState, action)=>{
}
/>
複製代碼
ref
屬性獲取到navigation
;ref
屬性以外,還接受onNavigationStateChange(prevState, newState, action)
屬性,每次當導航器所管理的state
發生改變時,都會回調該方法;
當導航器中的屏幕被打開時,它會收到一個navigation
prop,navigation
prop是整個導航環節的關鍵一員,接下來就詳細講解一下navigation
的做用。flex
注意:一個navigation有可能沒有navigate、setParams以及goBack,只有state與dispatch,因此在使用navigate時要進行判斷,若是沒有navigate可使用navigation去dispatch一個新的action。如:優化
const {navigation,theme,selectedTab}=this.props;
const resetAction = StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: 'HomePage',
params:{
theme:theme,
selectedTab:selectedTab
},
})
]
})
navigation.dispatch(resetAction)
複製代碼
提示:這裏的
reset
在2.0及之後版本中被從NavigationActions中移到了StackActions
中,使用時記得留意。
StackNavigator的navigation的額外功能:
當且僅當當前 navigator 是 stack navigator 時,this.props.navigation
上有一些附加功能。 這些函數是 navigate 和 goBack 的替代方法, 你可使用任何你喜歡的方法。 這些功能是:
navigation.navigate({routeName, params, action, key})
或 navigation.navigate(routeName, params, action)
export const AppStackNavigator = createStackNavigator({
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>
)
}
}
複製代碼
在使用React Navigation3x過程當中遇到任何問題均可以在React Navigation3x的視頻教程中尋找答案哈。
能夠經過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: 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完成,下文會講到。 在使用React Navigation3x過程當中遇到任何問題均可以在React Navigation3x的視頻教程中尋找答案哈。
goBack: function goBack(key)
:咱們能夠藉助goBack
返回到上一頁或者路由棧的指定頁面。
key
表示你要返回到頁面的頁面標識如id-1517035332238-4
,不是routeName。navigation.state.key
來得到頁面的標識。navigation.state
{params: {…}, key: "id-1517035332238-4", routeName: "Page1"} ```
複製代碼
export default class Page1 extends React.Component {
render() {
const {navigation} = this.props;
return <View style={{flex: 1, backgroundColor: "gray",}}>
<Text style={styles.text}>歡迎來到Page1</Text>
<Button
title="Go Back"
onPress={() => {
navigation.goBack();
}}
/>
</View>
}
}
複製代碼
dispatch: function dispatch(action)
:給當前界面設置action,會替換原來的跳轉,回退等事件。const resetAction = StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: 'HomePage',
params:{
theme:theme,
selectedTab:selectedTab
},
})
]
})
navigation.dispatch(resetAction)
複製代碼
Navigatie action會使用Navigate action的結果來更新當前的state。
方法原型:
navigate({routeName, params, action, key})
string or null
可選,要導航到的路由的標識符。若是已存在, 則導航回此路由。import { NavigationActions } from 'react-navigation'
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)
複製代碼
返回到前一個screen而且關閉當前screen.backaction creator接受一個可選的參數:
方法原型:
back(key)
String
可選,這個能夠和上文中講到的goBack的key是一個概念;import { NavigationActions } from 'react-navigation'
const backAction = NavigationActions.back();
this.props.navigation.dispatch(backAction);
複製代碼
經過SetParams咱們能夠修改指定頁面的Params。
import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
params: { title: 'HomePage' },
key: 'id-1517035332238-4',
});
複製代碼
有不少小夥伴可能會問:navigation中有setParams爲何還要有NavigationActions.setParams?
我從兩方面來回答一下這個問題:
NavigationActions.setParams
了;NavigationActions.setParams
能夠修改全部頁面的Params;在使用React Navigation3x過程當中遇到任何問題均可以在React Navigation3x的視頻教程中尋找答案哈。
Reset action刪掉全部的navigation state而且使用這個actions的結果來代替。
string or null
可選, 若是設置,具備給定 key 的導航器將重置。 若是爲null,則根導航器將重置。import { NavigationActions, StackActions } from 'react-navigation'
const resetAction = StackActions.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之上,你能夠這麼作:
import { NavigationActions, StackActions } from 'react-navigation'
const resetAction = StackActions.reset({
index: 1,
actions: [
NavigationActions.navigate({ routeName: 'WelcomePage'}),
NavigationActions.navigate({ routeName: 'HomePage'})
]
});
this.props.navigation.dispatch(resetAction);
複製代碼
Replace - 用另外一個路由替換指定的路由
Push - 在堆棧頂部添加一條路由,並導航至該路由. 與navigate的區別在於,若是有已經加載的頁面,navigate方法將跳轉到已經加載的頁面,而不會從新建立一個新的頁面。 push 老是會建立一個新的頁面,因此一個頁面能夠被屢次建立
import { StackActions } from 'react-navigation';
const pushAction = StackActions.push({
routeName: 'Profile',
params: {
myUserId: 9,
},
});
this.props.navigation.dispatch(pushAction);
複製代碼
The pop 一個能夠返回到堆棧中上一個路由到方法,經過設置參數 n,能夠指定返回的多少層。
import { StackActions } from 'react-navigation';
const popAction = StackActions.pop({
n: 1,
});
this.props.navigation.dispatch(popAction);
複製代碼
popToTop 一個能夠直接跳轉到堆棧最頂層,並銷燬其它全部頁面的方法,它在功能上與StackActions.pop({n:currentIndex})
相同。
import { StackActions } from 'react-navigation';
this.props.navigation.dispatch(StackActions.popToTop());
複製代碼
有一種場景:有的時候咱們須要在導航器中所定義的屏幕以外使用導航器來作頁面跳轉。
navigation
來完成的;const {navigation} = this.props;
來獲取navigation
;navigation
;navigation
呢?下面就給你們講解經過ref
屬性還得到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
以外的其餘兩種類型的導航器也是實用的哦;