前端状态管理框架redux和mobx解析

1,216 阅读7分钟

reduxmobx, 他们的思想都是一样的,都是解决跨组件数据传输的问题。实现数据持久化。

他们都可以应用于React(用于构建用户界面的 JavaScript 库)。

为什么我们需要统一的状态管理呢?

如果props能满足项目需求,我们可以不用引入reduxmobx,当遇到多层级,数据跨组建传输的场景,我们就可以引入状态管理,将他们放在顶层。

这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

拿我们云管平台举例,属于框架的功能:

权限管理(每个页面需要查用户和用户权限) 数据中心(很多页面需要拿数据中心id) 系统配置 或者,属于数据传递层级比较深,用的较多的功能:虚拟机等

下面我们分别看看redux和mobx的异同:

一、Redux

Redux 是什么 ? Redux 是前端应用的状态容器,提供可预测的状态管理,其基本定义可以用下列公式表示:

(state, action) => newState

其特点可以用以下三个原则来描述。

  • **单一数据源**:在 `Redux` 中,整个应用的状态以状态树的形式,被存储在一个单例的 `store` 中。
  • **状态数据只读**:惟一改变状态数据的方法是触发 `action`,`action` 是一个用于描述已发生事件的普通对象。
  • **使用纯函数修改状态**:在 `Redux` 中,通过纯函数,即 `reducer` 来定义如何修改 `state`。

从上述原则中,可以看出,构成 Redux 的主要元素有 action、reducer、store

Redux 具有单一数据源,触发 action 时,Redux store 在执行状态更新逻辑后,会执行注册在 store 上的事件处理函数。

代码:

  //view登陆
  //以AD/LDAP方式登录
  loginADLDAP = () => {
    const { validateFieldsAndScroll } = this.props.form;
    validateFieldsAndScroll((errors, values) => {
      if (errors) {
        return;
      }
      const loginType = 'ADLDAP';
      this.setState(values, () => {
        this.props.dispatch(login(values, loginType));
      });
    });
  };

//action
export function loginPost(json,project) {
    return {
        type: LOGIN,
        login: json,
        loginProject:project
    }
}

(以上是云管登陆代码截图)

  • `dispatch` 是 `View` 发出 `Action` 的唯一方法(事件)
  • `Store` 收到 `Action` 以后,必须给出一个新的 `State`,这样 `View` 才会发生变化。这种 `State` 的计算过程就叫做 `Reducer`。
  • `Reducer` 是一个函数,它接受 `Action` 和当前 `State` 作为参数,返回一个新的 `State`。

以上就是redux的基本介绍,延伸的还有redux的异步处理方案,中间件,应用状态的扁平化等,不赘述。

二 Mobx

任何源自应用状态的东西都应该自动地获得。其中包括UI、数据序列化、服务器通讯,等等。

React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用。

Mobx 是一个简单、可扩展的前端应用状态管理工具。Mobx 背后的哲学很简单:当应用状态更新时,所有依赖于这些应用状态的观察者(包括UI、服务端数据同步函数等),都应该自动得到细粒度地更新。

核心概念:

Observable state(可观察的状态)

MobX 为现有的数据结构(如对象,数组和类实例)添加了可观察的功能。

通过使用 @observable 装饰器(ES.Next)来给你的类属性添加注解就可以简单地完成这一切。

另外:

Derivations 可以理解为衍生,它是应用状态的观察者。

Mobx 中有两种形式的衍生,分别是 Computed valuesReactions

Computed values(计算值)

使用 MobX, 你可以定义在相关数据发生变化时自动更新的值。Computed values 是计算属性,它的数据通过纯函数由应用状态计算得来,当依赖的应用状态变更时,Mobx 自动触发计算属性的更新。

Reactions(反应)

Reactions 可简单理解为响应,与计算属性类似,它响应所依赖的应用状态的变更,不同的是,它不产生新的数据,而是输出相应的副作用(side effects),比如更新UI。

Actions

Actions 可以理解为动作,由应用中的各类事件触发。Actions 是变更应用状态的地方,可以帮助你更加清晰的组织你的代码。

下面这张图,反应了他们之间的关系。

可以有多个

//获取部门树
  @action getDeptTree = (params) => {
    userService.getDeptTree(params).then(rs => {
      runInAction(() => {
        this.deptTree = rs.data
      })
    })
  }

 componentDidMount() {
    this.props.userStore.getGroupTree(true)
  }

    render() {
    const { groupTree=[] } = this.props.userStore
    }
  1. 可以有多个`store`,把需要公用的数据,都放里面。规范,`store`里面到底放什么内容?
  2. 定义观察对象,接口获取数据,给对象。
  3. 需要的时候,直接从store里面拿。
  4. 其他的页面或者模块,也可以修改对象或者拿对象。

两者的区别:

reduxmobx
核心模块Action,Reducer,Store,没有调度器的概念;Action,Reducer,Derivation
store只有一个 Store, Store 和更改逻辑是分开的,带有分层 reducer的单一 Stor有多个 store
状态状态是不可改变的通常将状态包装成可观察对象,一旦状态对象变更,就能自动获得更新
编程思想更多的是遵循函数式编程思想设计更多偏向于面向对象编程和响应式编程
对象JavaScript对象可观察对象

单一store和多store

store是应用管理数据的地方,在Redux应用中,我们总是将所有共享的应用数据集中在一个大的store中,而Mobx则通常按模块将应用状态划分,在多个独立的store中管理。

JavaScript对象和可观察对象

Redux默认以JavaScript原生对象形式存储数据,而Mobx使用可观察对象: Redux需要手动追踪所有状态对象的变更;

Mobx中可以监听可观察对象,当其变更时将自动触发监听;

选择Mobx的原因

  • 学习成本少:Mobx基础知识很简单,学习了半小时官方文档和示例代码就搭建了新项目实例;而Redux确较繁琐,流程较多,需要配置,创建store,编写reducer,action,如果涉及异步任务,还需要引入redux-thunkredux-saga编写额外代码,Mobx流程相比就简单很多,并且不需要额外异步处理库;

  • 面向对象编程:Mobx支持面向对象编程,我们可以使用@observable and @observer,以面向对象编程方式使得JavaScript对象具有响应式能力;而Redux最推荐遵循函数式编程,当然Mobx也支持函数式编程;

  • 模版代码少:相对于Redux的各种模版代码,如,actionCreaterreducersagathunk等,Mobx则不需要编写这类模板代码;

不选择Mobx的可能原因

  • **过于自由**:Mobx提供的约定及模版代码很少,这导致开发代码编写很自由,如果不做一些约定,比较容易导致团队代码风格不统一,所以当团队成员较多时,确实需要添加一些约定;
  • **可拓展,可维护性**:也许你会担心Mobx能不能适应后期项目发展壮大呢?确实Mobx更适合用在中小型项目中,但这并不表示其不能支撑大型项目,关键在于大型项目通常需要特别注意可拓展性,可维护性,相比而言,规范的Redux更有优势,而Mobx更自由,需要我们自己制定一些规则来确保项目后期拓展,维护难易程度;当然对于“Redux更规范,更靠谱,应该使用Redux”或”Redux模版太多,太复杂了,应该选择Mobx”这类推断,我们也应该避免,这些都是相对而言。

每个框架都有各自的实现,特色,及其适用场景,正比如Redux流程更复杂,但熟悉流程后就更能把握它的一些基础/核心理念,使用起来可能更有心得及感悟;

而Mobx简单化,把大部分东西隐藏起来,如果不去特别研究就不能接触到它的核心/基本思想,也许使得开发者一直停留在使用层次。

所以无论是技术栈还是框架。类库,并没有绝对的比较我们就应该选择什么,抛弃什么,我们应该更关注它们解决什么问题。

它们解决问题的关注点,或者说实现方式是什么,它们的优缺点还有什么,哪一个更适合当前项目,以及项目未来发展。

参考资料

redux中文文档

mobx中文文档

Redux PK Mobx,谁更适合管理大规模应用的前端状态?