『React Navigation 3x系列教程』之React Navigation 3x開發指南

隨着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 Navigation3x的視頻教程,歡迎學習。bash

什麼是導航器?

導航器也能夠當作一個是普通的React組件,你能夠經過導航器來定義你的App的導航結構。 導航器還能夠渲染通用元素,例如能夠配置的標題欄和選項卡欄。app

在React Navigation中有如下7種類型的導航器:ide

  • createStackNavigator: 相似於普通的Navigator,屏幕上方導航欄;
  • createTabNavigator: createTabNavigator已棄用,使用createBottomTabNavigator和/或createMaterialTopTabNavigator替代;
  • createBottomTabNavigator:至關於iOS裏面的TabBarController,屏幕下方的標籤欄;
  • createMaterialTopTabNavigator:屏幕頂部的材料設計主題標籤欄;
  • createDrawerNavigator: 抽屜效果,側邊滑出;
  • createSwitchNavigator:SwitchNavigator 的用途是一次只顯示一個頁面。

你能夠經過以上7種導航器來建立你APP,能夠是其中一個也能夠多個組合,這個能夠根據具體的應用場景並結合每個導航器的特性進行選擇。函數

在開始學習7種導航器以前,咱們須要先了解兩個和導航關於概念:學習

  • Screen navigation prop(屏幕導航屬性):經過navigation能夠完成屏幕之間的調度操做,例如打開另外一個屏幕;
  • Screen navigationOptions(屏幕導航選項): 經過navigationOptions能夠定製導航器顯示屏幕的方式(例如:頭部標題,選項卡標籤等);

導航器所支持的Props

const SomeNav = createStackNavigator/createBottomTabNavigator/createMaterialTopTabNavigator/createDrawerNavigator/createSwitchNavigator({
  // 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的做用。flex

navigation包含一下功能:

  • navigate:跳轉到其餘界面;
  • state:屏幕的當前state;
  • setParams:改變路由的params;
  • goBack:關閉當前屏幕;
  • dispatch:向路由發送一個action;
  • addListener:訂閱導航生命週期的更新;
  • isFocused:true 標識屏幕獲取了焦點;
  • getParam:獲取具備回退的特定參數;
  • dangerouslyGetParent:返回父導航器;

注意:一個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 的替代方法, 你可使用任何你喜歡的方法。 這些功能是:

  • this.props.navigation
    • push - 導航到堆棧中的一個新的路由
    • pop - 返回堆棧中的上一個頁面
    • popToTop - 跳轉到堆棧中最頂層的頁面
    • replace - 用新路由替換當前路由
    • reset - 擦除導航器狀態並將其替換爲多個操做的結果
    • dismiss - 關閉當前棧

使用navigate進行界面之間的跳轉

  • navigation.navigate({routeName, params, action, key})navigation.navigate(routeName, params, action)
    • routeName:要跳轉到的界面的路由名,也就是在導航其中配置的路由名;
    • params:要傳遞給下一個界面的參數;
    • action:若是該界面是一個navigator的話,將運行這個sub-action;
    • key:要導航到的路由的可選標識符。 若是已存在,將後退到此路由;
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的視頻教程中尋找答案哈。

使用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完成,下文會講到。 在使用React Navigation3x過程當中遇到任何問題均可以在React Navigation3x的視頻教程中尋找答案哈。

使用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={{flex: 1, backgroundColor: "gray",}}>
            <Text style={styles.text}>歡迎來到Page1</Text>
            <Button
                title="Go Back"
                onPress={() => {
                    navigation.goBack();
                }}
            />
        </View>
    }
}
複製代碼

經過dispatch發送一個action

  • dispatch: function dispatch(action):給當前界面設置action,會替換原來的跳轉,回退等事件。
const resetAction = StackActions.reset({
	index: 0,
	actions: [
	    NavigationActions.navigate({
	        routeName: 'HomePage',
	        params:{
	            theme:theme,
	            selectedTab:selectedTab
	        },
	    })
	]
	})
navigation.dispatch(resetAction)
複製代碼

NavigationActions

  • Navigate : 導航到其餘的頁面;
  • Back : 返回到上一個頁面;
  • Set Params : 設置指定頁面的Params;
  • Init : 初始化一個 state 若是 state 是 undefined;

Navigate:

Navigatie action會使用Navigate action的結果來更新當前的state。

方法原型:navigate({routeName, params, action, key})

  • routeName:字符串,必選項,在app的router裏註冊的導航目的地的routeName。
  • params:對象,可選項,融合進目的地route的參數。
  • actions:對象,可選項(高級),若是screen也是一個navigator,次級action能夠在子router中運行。在文檔中描述的任何actions均可以做爲次級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)
複製代碼

Back

返回到前一個screen而且關閉當前screen.backaction creator接受一個可選的參數:

方法原型:back(key)

  • key:String 可選,這個能夠和上文中講到的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?

我從兩方面來回答一下這個問題:

  1. 在上文中講到過navigation中有可能只有state與dispatch,這個時候若是要修改頁面的Params,則只能經過NavigationActions.setParams了;
  2. 另外,navigation.setParams只能修改當前頁面的Params,而NavigationActions.setParams能夠修改全部頁面的Params;

在使用React Navigation3x過程當中遇到任何問題均可以在React Navigation3x的視頻教程中尋找答案哈。

StackActions

  • Reset : 重置當前 state 到一個新的state;
  • Replace : 使用另外一個路由替換指定的路由;
  • Push : 在堆棧頂部添加一個頁面,而後跳轉到該頁面;
  • Pop : 跳轉到上一個頁面;
  • PopToTop : 跳轉到堆棧最頂層的頁面,並銷燬其餘全部頁面;

Reset:

Reset action刪掉全部的navigation state而且使用這個actions的結果來代替。

  • index,數組,必選,navigation state中route數組中激活route的index。
  • actions,數組,必選項,Navigation Actions數組,將會替代navigation state。
  • key: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

Replace - 用另外一個路由替換指定的路由

  • key - string - 被替換的路由的 key,若是未指定,最近的路由將會被替換
  • newKey - string - 用於替換路線的 Key。 若是未提供,則自動生成。
  • routeName - string - routeName用於替換路由。
  • params - object - 要傳入替換路由的參數。
  • action - object - 可選的子動做。
  • immediate* - boolean - 目前沒有效果, 這是 stack navigator 支持動畫替換(它目前不支持)的佔位符。

push

Push - 在堆棧頂部添加一條路由,並導航至該路由. 與navigate的區別在於,若是有已經加載的頁面,navigate方法將跳轉到已經加載的頁面,而不會從新建立一個新的頁面。 push 老是會建立一個新的頁面,因此一個頁面能夠被屢次建立

  • routeName - string - routeName用於替換路由。
  • params - object - 將合併到目標路由的參數(經過this.props.navigation.state.params在目標路由獲取)。
  • action - Object - 可選 - (高級)若是頁面是 navigator,則是在子路由器中運行的子操做。
import { StackActions } from 'react-navigation';

const pushAction = StackActions.push({
  routeName: 'Profile',
  params: {
    myUserId: 9,
  },
});

this.props.navigation.dispatch(pushAction);
複製代碼

pop

The pop 一個能夠返回到堆棧中上一個路由到方法,經過設置參數 n,能夠指定返回的多少層。

  • n - number - 返回的層數
import { StackActions } from 'react-navigation';

const popAction = StackActions.pop({
  n: 1,
});

this.props.navigation.dispatch(popAction);
複製代碼

popToTop

popToTop 一個能夠直接跳轉到堆棧最頂層,並銷燬其它全部頁面的方法,它在功能上與StackActions.pop({n:currentIndex})相同。

import { StackActions } from 'react-navigation';

this.props.navigation.dispatch(StackActions.popToTop());
複製代碼

如何支持Schema跳轉?

Deep Linking

還有那些應用場景?

在導航器屏幕以外使用導航功能(巧用導航器的ref)

有一種場景:有的時候咱們須要在導航器中所定義的屏幕以外使用導航器來作頁面跳轉。

  • 屏幕之間的跳轉是須要藉助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以外的其餘兩種類型的導航器也是實用的哦;

相關文章
相關標籤/搜索