年前公司由一个项目是使用 ReactNative
来开发的所以遇到了一些问题,比较影响开发进程的就是路由问题了,实际上就是 ReactNavigation
这个组件比较难懂,这里给大家讲解一下,希望大家少踩点坑.另外本篇文章使用的是 TypeScript
环境
主要讲解的还是 如何使用Mobx记录ReactNative中路由的状态
但是会穿插一些小内容,这里虽然讲到的是 Mobx
,如果你使用的是 redux
的话也不用灰心,原理都是一样的,只要能看懂这篇文章,那我相信对于 ReactNavigation
有了更深的了解
ReactNavigation
的官网上面有redux
的教程
API介绍
在开发之前我先向大家介绍一下需要使用到的API
- NavigationActions
- getStateForAction
- addNavigationHelpers
NavigationActions
里面存在了很多方法,在这里我先讲 NavigationActions.init()
,实际上是用来获取 初始状态
的路由信息,当然你也可以不使用这个API,来自己手动写出初始的路由状态,但是我不太推荐这个方法,第一个是路由扩展的时候你又要去重新改,第二个是ReactNavigation
这个库的改动很频繁,说不定哪一天就变了个格式,到时候你又要重写
getStateForAction(action,state)
提供一个 action
和 上一次的路由状态
从而获取最新的路由状态
addNavigationHelpers(navigation)
是记录路由状态的核心方法,如何理解呢?我们看到他的参数是 navigation
这是一个对象,我们这里只讲其中的两个值 state
和 dispatch
,这里的 dispatch
和 redux
的dispatch
的概念是相似的,在 ReactNavigation
里面每次路由的改变,他都会在里面触发 dispatch
并且传递一个 action
,有了action
之后可以通过getStateForAction
来获取当前路由的state
.state
则是保证当前建立的路由信息和Mobx
保存的路由信息的一致性
实现代码
import * as React from "react"; import * as stores from "@stores"; import Router from "./router";// 自己定义的路由结构 import { Provider } from "mobx-react/native"; import { addNavigationHelpers } from "react-navigation"; import { observer } from "mobx-react"; import { useStrict } from "mobx"; useStrict(true); console.disableYellowBox = true; interface Props {} interface State {} @observer export default class App extends React.Component<Props,State> { constructor(props,context) { super(props,context); } render() { let { nav } = stores; return ( <Provider {...stores}> <Router navigation={addNavigationHelpers({ dispatch: nav.dispatch.bind(nav),state: nav.navigatorState })} /> </Provider> ); } }
// store import { observable,action,computed } from "mobx"; import { NavigationActions,NavigationState } from "react-navigation"; import RootRouter from "@router/index"; // 自己定义的路由结构 export class NavStore { @observable.ref navigatorState: NavigationState; constructor() { this.navigatorState = RootRouter.router.getStateForAction( NavigationActions.init(),null ); } // 提供一个获取当前路由层级的功能 private getRouterName(state) { let childRouters = state.routes; if (childRouters && childRouters.length > 0) { let curRouterName = childRouters[state.index].routeName; let nextRouterName = this.getRouterName(childRouters[state.index]); let result = nextRouterName ? "-" + nextRouterName : ""; return curRouterName + result; } return ""; } @computed get routerName() { return this.getRouterName(this.navigatorState); } @action dispatch(action) { const prevIoUsNavState = this.navigatorState; return (this.navigatorState = RootRouter.router.getStateForAction( action,prevIoUsNavState )); } } export default new NavStore();
大家对 Mobx
不熟悉的话其实看我前面API的介绍就好了,核心就是addNavigationHelpers
提供了覆盖 dispatch
和 同步state
的功能,只要理解了这个,无论你使用 redux
还是 Mobx
都不是问题
另外一些小问题
在开发 ReactNative
的时候可能在某个页面需要跳转,这个时候你不得不把 navigation
从头传到底,这种体验很糟糕我更推荐使用一些 API
去 快速跳转
或者 传递参数
import { NavigationActions } from "react-navigation"; // 使用我上面定义的dispatch // 简单跳转 dispatch( NavigationActions.navigate({ routeName: "Search" }) ); // 带参数跳转 dispatch( NavigationActions.navigate({ routeName: "Search",params : { name : "Jason "} }) ) // 多级跳转 dispatch( NavigationActions.navigate({ routeName: "Search",action : NavigationActions.navigate({ routeName: "User" }) }) );
这篇文章是年前的
ReactNavigation
文档,刚刚上去又看了一下发现有些改动,我研究下有没有需要改动的地方,不过大致看了下,应该没啥变化
参考资料: