React-navigation 路由任意跳轉總結
前言
使用ReactNative很長時間了,官方版本更新的太快了,最近才把公司的專案升級到最新,其中導航,官方已經遺棄了Navigator,推薦使用React-Navigation.基礎的東西就不介紹了,可以去官網看看。
介紹
本文主要解決這樣一個場景,假如有4個頁面,A,B,C,D.我們跳轉的順序是A->B->C->D,現在想從D回到B,官方沒有提供直接的介面讓我們操作。結合前人的經驗,本人親自驗證後,做出此總結(廢話有點多 - -!)。
正題
-
使用NavigationService
這個是官方介紹的一種抽取一個公共類來操作跳轉方法,該方法用於解放雙手,媽媽再也不用擔心我不停的寫this.props.navigation了,本例也採用這種方式來實現我們的需求。具體程式碼如下:
import {NavigationActions} from 'react-navigation'; let _navigator; let _routers; let _navigation; /** * 設定頂層路由導航 * @param navigatorRef */ function setTopLevelNavigator(navigatorRef) { _navigator = navigatorRef; } /** * 設定當前路由棧和導航物件 * @param routers * @param navigation */ function setRouters(routers, navigation) { _routers = routers; _navigation = navigation; } /** * 跳轉到指定頁面 * @param routeName * @param params */ function navigate(routeName, params) { _navigator.dispatch( NavigationActions.navigate({ type: NavigationActions.NAVIGATE, routeName, params, }) ); } /** * 返回到頂層 */ function popToTop() { _navigator.dispatch(NavigationActions.popToTop()) } /** * 返回第n個頁面 * @param n */ function popToN(n) { if (n <= 0) { return; } let len = _routers.length; if (len < n || n === len - 1) { this.popToTop(); return; } _navigation.goBack(_routers[len - n].key); } /** * 返回 */ function goBack() { _navigator.dispatch(NavigationActions.back({type: NavigationActions.BACK})); } /** * 返回到任意頁面 * @param routeName */ function popToRouter(routeName) { if (!routeName) { this.goBack(); return; } let len = _routers.length; for (let i = 0; i < len - 1; i++) { let route = _routers[i]; if (routeName === route.routeName && i !== len - 1) { _navigation.goBack(_routers[i + 1].key); return; } } } export default { setTopLevelNavigator, setRouters, navigate, popToRouter, goBack, popToTop }; 複製程式碼
-
在入口出將頂層導航設定到公共方法中
這裡需要在配置React-navigation頂層導航的地方,將頂層導航設定到公共導航類中,程式碼如下:
import React, {Component} from 'react' import NavigationService from './NavigationService' import { StackNavigator} from 'react-navigation' import Page1 from "../page/Page1"; import Page2 from "../page/Page2"; import Page3 from "../page/Page3"; import Page4 from "../page/Page4"; import Page5 from "../page/Page5"; const screens ={ Page1:{ screen:Page1, }, Page2:{ screen:Page2, navigationOptions:{ title:'Page2' } }, Page3:{ screen:Page3, navigationOptions:{ title:'Page3' } }, Page4:{ screen:Page4, navigationOptions:{ title:'Page4' } }, Page5:{ screen:Page5, navigationOptions:{ title:'Page5' } } } const Nav = new StackNavigator({ ...screens }) class App extends Component { render() { return ( <Nav ref={navigatorRef => { NavigationService.setTopLevelNavigator(navigatorRef);//設定頂層導航 }} /> ) } } export default App; 複製程式碼
-
使用NavigationService
簡單的跳轉:
//對應this.props.navigation.navigate(routeName) NavigationService.navigate('Page2'); //對應this.props.navigation.goBack(); NavigationService.goBack(); //返回到路由棧頂層 NavigationService.popToTop(); //返回到第n層頁面 NavigationService.popToN(n); //返回到指定頁面(routeName頁面必須在當前路由棧中) NavigationService.popToRouter(routeName) 複製程式碼
上面的前三個方法可以直接用,後面兩個是用於返回任意頁面,需要在路由棧的頂層頁面配置一下,程式碼如下:
static navigationOptions = { header:({navigation}) =>{ let {state:{routes}} = navigation; NavigationService.setRouters(routes, navigation); return null; } }; 複製程式碼
上面程式碼大意是,拿到當前路由的路由棧(一個包含當前路由資訊的陣列),有路由陣列了,我們就可以為所欲為之為所欲為了。
-
解放雙手之傳參
使用過React-navigation的都知道,如果要接受上個頁面的傳來的引數,就需要寫:this.props.navigation.params.***.如果專案中很多頁面需要傳遞引數,那這程式碼就噁心至極。如果是升級之前的程式碼,那需要全域性替換this.props,現在有個大神替我們解決了這個麻煩,原始碼地址react-navigation-props-mapper;
使用很簡單隻需要在接受引數的頁面類的頭部加上一句註解(當然使用之前需要引入大神的庫):
import { withMappedNavigationProps } from 'react-navigation-props-mapper' @withMappedNavigationProps() export class SomeScreen extends Component { 複製程式碼
如果你使用了mobx的observer註解,不好意思,這裡會有衝突,解決辦法就是把@observer放下面。
若有需要看本例原始碼,請移步這裡,如果對您有用,希望star一下,萬分感謝,如果有說的不對的地方,還望各位指正,拜謝。