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
使用很简单只需要在接受参数的页面类的头部加上一句注解
import { withMappedNavigationProps } from 'react-navigation-props-mapper'
@withMappedNavigationProps()
export class SomeScreen extends Component {
复制代码
如果你使用了mobx的observer注解,不好意思,这里会有冲突,解决办法就是把@observer放下面。