一、react-navigation的初使用
createStackNavigator ==> createSwitchNavigator ==> createAppContainer
createBottomTabNavigator ==> 自定義的底部Tab
NavigationActions 和 StackActions 可以獲取navigation的方法名
二、this.props.navigation使用的方法和屬性
詳細請看: react-navigation 3.x版本的push、navigate、goback、pop、dispatch等常用方法
1. 應用中的每個頁面組件都會自動提供 this.props.navigation
this.props.navigation可以獲取的一些方法:

1 navigate - 轉到另一個頁面, 計算出需要執行的操作 (常用) 2 goBack - 關閉活動屏幕並在堆棧中向后移動 (常用) 3 addListener - 訂閱導航生命周期的更新 4 isFocused - 函數返回 true 如果屏幕焦點和 false 否則。 5 state - 當前狀態/路由 (常用)
6 setParams - 對路由的參數進行更改 (常用) 7 getParam - 獲取具有回退的特定參數 (常用) 8 dispatch - 向路由發送 action (常用) 9 dangerouslyGetParent - 返回父級 navigator 的函數
注意: this.props.navigation並不是在所有頁面(組件)中都可以使用,而是必須在StackNavigator、DrawerNavigator中聲明的screen組件,才可以使用this.props.navigation
也就是說,screen組件會自動獲得這個props
this.props.navigation
上還有一些方法取決於當前 navigator 的附加函數(StackNavigator 和 DrawerNavigator)
2. 如果是StackNavigator,除了以上方法,this.props.navigation還提供如下的一些方法:

1 push - 推一個新的路由到堆棧 (常用) 2 pop - 返回堆棧中的上一個頁面 (常用) 3 popToTop - 跳轉到堆棧中最頂層的頁面 (常用) 4 replace - 用新路由替換當前路由 5 reset- 操作會擦除整個導航狀態,並將其替換為多個操作的結果。 (常用) 6 dismiss - 關閉當前堆棧
3. 如果是DrawerNavigator,除了以上方法,this.props.navigation還提供如下的一些方法:

1 openDrawer - 打開 2 closeDrawer - 關閉 3 toggleDrawer - 切換,如果是打開則關閉,反之亦然
由於筆者沒有使用過DrawerNavigator,在此就不做說明;
以上內容均摘自react-navigation的官網,但是官網有點繁瑣,寫此以自用,有讀者也是我的幸運。
三、react-navigation的特殊方法
===============================================================
==> 清空堆棧,跳轉指定頁面
import {NavigationActions, StackActions} from 'react-navigation' const resetAction = StackAction.reset({ index: 0, actions: [NAvigationActions.navigate({ routeName: 'HomeScreen'})], }); //使用
this.props.navigation.dispatch(resetaction)
說明: 上面的方法是使用dispatch重寫了reset方法,
也可以直接使用reset方法:this.props.navigation.reset()
import { NavigationActions } from 'react-navigation'; navigation.reset([NavigationActions.navigate({ routeName: 'HomeScreen' })], 0)
========================================================================
//在不在StackNavigation的堆棧中的頁面,如何使用navigation
1.在主Navigator的組件中添加ref,並導出
//StackNavigator來自createStackNavigator方法
const MainNavigator = createAppContainer(StackNavigator); import {setTopLevelNavigator} from 'xxx.js' export default calss Navigator extends Component{ render() { return( <MainNavigator ref={navigatorRef => {setTopLevelNavigator(navigatorRef )}} //setTopLevelNavigator來自需要使用的頁面
/>
) } }
說明: 將MainNavigator 通過ref 傳遞給 其他頁面傳過來的 setTopLevelNavigator
2.在需要使用的頁面,接收這個ref引用,如xxx.js
let _navigator; export function setTopLevelNavigator(navigatorRef ) { _navigator = navigatorRef } // 定義navigate 方法
function navigate(routeName, params) { _navigator && _navigator.dispatch( NavigationActions.navigate({ type: NavigationActions.NAVIGATE, routeName, params }) ) } // 定義dispatch方法
function dispatch(params) { _navigator && _navigator.dispatch( params ) } //使用,直接使用上面的方法即可 dispatch(resetAction) //resetAction同上
navigate("Home", {title: 'profile'})
說明: 通過setTopLevelNavigator去主導航頁面接收navigation相關的方法
另外: 使用withNavigation(Component) 可以使得組件攜帶navigation相關的方法
withNavigation是一個更高階的組件,它將navigationprop 傳遞給一個包裝組件。當你不能navigation直接將prop 傳遞給組件時,或者在深度嵌套的子級的情況下不想傳遞它時,它很有用。
withNavigation(Component) 返回一個Component。
import React from 'react'; import { Button } from 'react-native'; import { withNavigation } from 'react-navigation'; class MyBackButton extends React.Component { render() { return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />; //此處可以使用navigation相關方法
} } // withNavigation returns a component that wraps MyBackButton and passes in the // navigation prop
export default withNavigation(MyBackButton);
========================================================================
==》阻止多次點擊重復跳轉同一頁面
const navigateOnce = (getStateForAction) => (action, lastState) => { const {type, routeName, params} = action; return ( lastState && (type === StackActions.PUSH) && //此處原先使用NavigationActions.NAVIGATE
routeName === lastState.routes[lastState.routes.length - 1].routeName && JSON.stringify(params) === JSON.stringify(lastState.routes[lastState.routes.length - 1].params) ) ? null : getStateForAction(action, lastState) } //使用,MainNavigator是主導航頁面通過createAppContainer方法的返回值
MainNavigator.router.getStateForAction = navigateOnce(MainNavigator.router.getStateForAction)
說明: MainNavigator經過 getStateForAction 檢查校驗,阻止多次點擊跳轉相同頁面的情況發生
注意: 當你使用createSwitchNavigator時,就在路由數組外在套上一層switch數組,所以 lastState.routes[lastState.routes.length - 1] 可能取不到想要的值,因為還有一層數組
6月26日修改:
當使用了createSwitchNavigator時,修改上面的 navigateOnce 方法
const MainSwitch = createSwitchNavigator({ MainStack: MainStack, ... //其他
}) const MainNavigator = createAppContainer(MainSwitch); const navigateOnce = (getStateForAction) => (action, lastState) => { const {type, routeName, params} = action; //此處需要注意,使用了createSwitchNavigator后,lastState.routes[lastState.routes.length - 1]拿不到我們想要的那個對象
const mainStackRoutes = lastState && lastState.routes.find((item)=>item.key === "MainStack"); //拿到我們想要的那個對象
return ( mainStackRoutes && (type === StackActions.PUSH) && //此處原先使用NavigationActions.NAVIGATE
routeName === mainStackRoutes .routes[mainStackRoutes .routes.length - 1].routeName && JSON.stringify(params) === JSON.stringify(mainStackRoutes .routes[mainStackRoutes .routes.length - 1].params) ) ? null : getStateForAction(action, lastState) } //使用,MainNavigator是主導航頁面通過createAppContainer方法的返回值
MainNavigator.router.getStateForAction = navigateOnce(MainNavigator.router.getStateForAction)
但是,當我們使用了createSwitchNavigator時,又使用了createDrawerNavigator,於是,再次修改上面的 navigateOnce 方法
const MainDrawer = createDrawerNavigator({ MainStack: MainStack, ... //其他
}, { order: ['MainStack'], initialRouteName: 'MainStack', ... }) const MainSwitch = createSwitchNavigator({ MainDrawer : MainDrawer , StartPresentation: StartPresentation, //APP啟動頁
... //其他
}, { initialRouteName: 'StartPresentation', ... }) const MainNavigator = createAppContainer(MainSwitch); const navigateOnce = (getStateForAction) => (action, lastState) => { const {type, routeName, params} = action; //使用了createDrawerNavigator后,上面的方法也拿不到我們想要的對象
const mainDrawerRoutes = lastState && lastState.routes.find((item)=>item.key === "MainDrawer "); //拿到我們想要的那個對象
//此處需要注意,使用了createSwitchNavigator后,lastState.routes[lastState.routes.length - 1]拿不到我們想要的那個對象
const mainStackRoutes = mainDrawerRoutes&& mainDrawerRoutes.routes.find((item)=>item.key === "MainStack"); //拿到我們想要的那個對象
return ( mainStackRoutes && (type === StackActions.PUSH) && //此處原先使用NavigationActions.NAVIGATE
routeName === mainStackRoutes .routes[mainStackRoutes .routes.length - 1].routeName && JSON.stringify(params) === JSON.stringify(mainStackRoutes .routes[mainStackRoutes .routes.length - 1].params) ) ? null : getStateForAction(action, lastState) } //使用,MainNavigator是主導航頁面通過createAppContainer方法的返回值
MainNavigator.router.getStateForAction = navigateOnce(MainNavigator.router.getStateForAction)
總而言之,當我們修改navigation代碼結構時,navigateOnce 方法也要隨着修改,靈活一點。。。