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一下,万分感谢,如果有说的不对的地方,还望各位指正,拜谢。