Mobx在机票React Native项目中的实践

2015年加入去哪儿网机票事业部-用户产品部,从事Android客户端和基于ReactNative泛前端上的机票业务研发工作。有复杂业务的ReactNative项目架构设计、Redux/Mobx数据流管理方案设计、性能优化等经验,专注于可快速迭代和扩展的技术方案的研究。

1. 前言 

(1)数据流管理对 React Native 项目的重要性

React Native 给客户端提供了高性能的,具有 native 体验的,跨平台的开发方案。对提高开发效率,提高移动 web 产品体验等方面具有显著效果,并且赋予iOS、Android 简单可靠的热更新能力。机票在客户端的主流程业务已经陆续切换为 React Native 实现。对于 React Native(后文中简称 RN)项目来说最重要的是数据流管理,也就是对业务数据、业务逻辑的管理。因此数据流管理的实现对 RN 项目的结构层次划分、代码复杂度、后续的可维护性都是至关重要的。

(2)以往数据流管理方案的缺点

在以往的 React Native 项目中,我们采用 Redux 进行数据流管理。Reudx 提供了一种简单单向、可预测的数据流管理方式,很好的解决了 RN 项目对数据流管理的诉求,但是在使用过程中遇到了一些缺陷和痛点:

1)维护成本高,Redux 中 action 和 reducer 割裂,两者之前的映射关系过于依赖约定,维护成本高,查找代码不方便。

2)性能调优繁琐,需要同时配置 mapStateToProps 和 mapDispatchToProps,在配置过程中需要考虑不能引入额外的属性,以防引起过度渲染。

3)单 store 的局限性,Redux 中只有一棵 state 树,当多个同类型页面并存时,难以解决数据混淆问题。

为了解决以上遇到的问题,我们在 RN 项目中,引入了 Mobx 库进行数据流管理。

2. Mobx是什么 

Mobx 的宗旨是对开发者隐藏数据与 View 之间的依赖关系的实现,从而提供一种更简单的管理方案。Mobx 的核心理念是简单、可扩展,它能够实现可预测的、清晰的数据流管理,并且在使用方式上比 Redux 更简单,学习成本更低。

Mobx 的数据流如上图所示。Store 是所以数据和影响数据改变的集合,包括:① 改变数据的 Action,由 View 中事件调用触发,是改变 Store 中属性的唯一方式② 数据的当前状态 State③ 根据原始数据衍生计算出来的状态,是自动触发的在整个数据流中,通过事件驱动(UI 事件、网络请求等)触发 Actions,在 Actions 中修改了 State 中的值,这里的 State 为视图展示所需要的数据,然后根据新的 State 自动衍生出所需要的计算属性值(computed values),这些 state 的改变,会引起视图的自动刷新。

Mobx 最大的特点是内部维护了数据状态与 view 之间的依赖关系,当数据发生改变时,能自动刷新对应的 view,这样很大程度上减少了配置依赖所需要的开发成本 , 也极大的减少了人为触发带来的错误。

3. 采用Mobx后的React Native项目结构 

在机票的 RN 项目中,引入 Mobx 后的项目结构主要分为四个模块。如下图所示:

(1)视图模块

视图模块以页面为维度进行划分,顶层的是入口页面,若是需要支持 Ext.router 导航到这个页面,则需要继承自 QView 类,否则继承自 Component 类即可。在入口页面只处理组件的细分和组合、生命周期的触发、交互事件的绑定、store 的绑定,对于具体 UI 布局的实现,根据页面的结构细分为不同的组件来实现。为了保持视图层的纯净,所有数据相关的处理都交给 Store 层来处理。

(2)Store 模块

这个模块是数据流管理的核心,用到了 Mobx 的核心概念:observable、computed value、action 等,没有基础的同学可以先行了解一下 Mobx 的基础知识。Store 中管理了项目中需要的所有数据,是个数据集合,Mobx 中是允许存在多个数据状态树的,并且页面和数据状态树之间的依赖关系也没有限制。但是,为了结构清晰、数据便于管理,我们以页面维度划分 Store,一个页面对应的一个数据状态树,也就是一个 PageStore。若是数据状态树比较复杂,我们可以根据面向对象的思想进行细分,结构如下图:

1)GenericPageStore 是所有 PageStore 的基类,是将页面间的共同属性和方法抽取出来,包括:页面的生命周期处理方法、网络数据等。2)XXXPageStore 类主要管理对应的 PageView 的生命周期的数据状态,以及外部数据的获取子 model store 的初始化。3)子 model 主要根据数据类型或者组件粒度来进行细分,在其中定义组件显示所需要的属性,也就是 observable 属性;基于原始数据衍生出的属性 computed value,通常用在原始数据不能满足显示需要的时候;改变数据状态的方法 action,action 不承载具体的业务实现,只做 view、stores、功能实现的衔接器,功能实现划归到 computations 模块中(会在下面细说)。

(3)业务逻辑模块 Computations

在机票的客户端项目中,有较多的业务逻辑判断和计算,尤其是在航班筛选、用户生单等主流程项目中。若是将业务逻辑都写到 Store 模块,那么 Store 会变得非常臃肿,后期维护也会变得困难,因此将业务逻辑的具体实现都放到 computation 模块中,减轻 Store 模块的负担,也使项目结构更加清晰。在这个模块遵循函数式编程规则,computations本身不保存任何状态,内部计算仅依赖输入参数,返回给调用者(store)计算结果。

(4)数据仓库 Repository

这个模块主要提供原始数据来源,在 RN 项目中主要包括网络请求数据和从native 获取数据,分别由类 HotdogApi 和 NativeApi 来实现。

4. 关键细节的实现 

(1)Mobx 的数据流实现第一步:创建 store 实例在每个入口页面的构造函数中创建 store 的实例,通过 组件将 store 作用到 react 的上下文,这样该页面下的任意子组件都可以通过 @inject 获取到 store。

第二步:声明被观察的属性使用 @observable 将 Store 的属性变为一个被观察的值。

第三步:将组件设置为观察者使用 @inject 可以在组件中获取到 store 中的任意属性,然后使用 @observer ,将组件变为观察者,响应 store 中 observable 属性状态的变化。这样,当改变 store 中属性时,组件就是自动更新,从而实现数据驱动视图。

第四步:通过 action 改变 store 中的数据action 是改变 store 中数据的唯一方法,在页面交互事件中,可以调用 action 改变 store 中的属性,从而达到改变 view 状态的目的。

(2)PageStore 与子 model 之间的关系处理当一个页面的数据比较复杂时,需要将 PageStore 细分为子 model 进行管理,那么 PageStore 中持有所有子 model 的实例,便于在 view 中通过 store 获取到对应的子 model。

另一方面,为了每个子 model 方便处理业务逻辑,则在 PageStore 获取到原始数据后,每个子 model 都需要有对原始数据的引用,这样当业务需求有迭代时,只需要修改子 model 中的逻辑即可,而不会影响其他模块。

(3)网络状态机的实现在机票客户端中,每个页面的网络状态基本相同,所以设计了网络状态机。用 NetIndicatorStore 类来统一管理网络请求的参数、网络请求的状态、请求返回结果、对应的页面加载框的状态,并且基于网络的基础状态衍生出是否请求异常、是否正在加载中等 view 显示常用的数据。

(4)使用 async/await 和 Promise 将异步串行化在机票项目中,异步过程是非常常见的,比如网络请求、通过 native 桥获取数据等均是异步过程。对于异步过程,传统的回调方式一直存在多层嵌套回调的问题,使用复杂并且不利于代码逻辑理解。所以,我们规范使用 Promise 来处理异步过程,Promise 强大的多重链式调用可以避免层层嵌套回调,但是它并没有解决回调本身,异步的处理结果的接收还是使用回调形式。于是,我们引入 async/await 关键字,将原本异步过程的代码写成同步的形式,即将异步串行化,简化了异步过程的编码,增强了代码的可读性。

5. 基于Mobx数据流管理方案的优点 

Mobx 和 Redux 都是当下比较流行的数据流管理库,在机票项目实践中,Mobx 不仅解决了 Redux 中遇到的配置繁琐、维护成本大、单 store 的局限等问题,还具有以下优势:1)适用于业务复杂的项目。Mobx 面向对象的思想更利于业务模型的拆分,对于业务较为复杂的机票项目来说,更便于设计清晰、层次化的项目架构,便于后续复杂业务的快速迭代。2)数据流触发简单便于开发调试。Mobx 中核心的 state 和 action 以类的单位进行集成划分,数据流动由函数调用一气呵成,输入数据和结果状态没有割裂,便于代码查找和开发调试。3)性能优化成本低。Mobx 中 View 与数据之间的关系全部由内部处理,减少了人为配置的成本,另外 Mobx 内部对 ComponentShouldUpdate 方法进行了重写,做了很多避免 View 过度渲染的优化,减少了后期性能优化的成本,使开发者可以更专注于业务实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值