React-navigation 路由任意跳转总结

4,826 阅读3分钟

React-navigation 路由任意跳转总结

前言

使用ReactNative很长时间了,官方版本更新的太快了,最近才把公司的项目升级到最新,其中导航,官方已经遗弃了Navigator,推荐使用React-Navigation.基础的东西就不介绍了,可以去官网看看。

介绍

本文主要解决这样一个场景,假如有4个页面,A,B,C,D.我们跳转的顺序是A->B->C->D,现在想从D回到B,官方没有提供直接的接口让我们操作。结合前人的经验,本人亲自验证后,做出此总结(废话有点多 - -!)。

正题

  1. 使用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
     };
    
  2. 在入口出将顶层导航设置到公共方法中

    这里需要在配置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;
    
  3. 使用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;
         }
     };
    

    上面代码大意是,拿到当前路由的路由栈(一个包含当前路由信息的数组),有路由数组了,我们就可以为所欲为之为所欲为了。

  4. 解放双手之传参

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