Skip to content

状态管理介绍

在目前前端的组件化开发风潮中,无论是 PC 端还是移动端,对于组件化来讲有一个非常重要的就是状态管理。要理解什么状态管理,首先就要理解什么是状态。

实际上,状态的概念非常简单,就是每个组件自身可以维护一些数据。而由于组件与组件之间存在一些关系(例如父子关系、兄弟关系),这就避免不了组件之间要进行数据的传递,这也就是所谓的组件状态管理出现的背景。

image-20220627103352425

如果使用传统的 porps 或者自定义事件的形式来传递组件的数据,就会显得非常的繁琐,一个组件状态更新,需要一层一层传递到根组件,再由根组件一层一层往下传递。这样一个应用的组件层数嵌套得越深,工作量就会变得越大。

在这样的背景下,专门用于状态管理的库就出现了。

image-20220627105559707

状态管理库的核心思想很简单,专门拿一个 store 的仓库来管理所有组件的状态,假如一个组件状态更新后,同步更新仓库中的状态,这样另一个组件再获取最新的状态时,也不用向之前那样层层传递,直接从仓库获取最近的状态即可。

目前,市面上比较流行的状态管理库有:

  • Flux
  • Vuex
  • Redux
  • Mobx

Flux#

2013 年,Facebook 亮出 React 的时候,也跟着带出了 FluxFacebook 认为两者相辅相成,结合在一起才能构建大型的 JavaScript 应用。

Flux 的组成:

  • View: 视图层
  • Action: 动作,即数据改变的消息对象(可通过事件触发、测试用例触发等)
    • Store 的改变只能通过 Action
    • 具体 Action 的处理逻辑一般放在 Store
    • Action 对象包含 type(类型)与 payload(传递参数)
    • Action 仅仅是改变 Store 的一个动作,一般包含该动作的类型、传递的数据
  • Dispatcher: 派发器,接收 Actions,发给所有的 Store
  • Store: 数据层,存放应用状态与更新状态的方法,一旦发生变动,就提醒 Views 更新页面

image-20220627105617920

Flux 的特点:

  • 单向数据流。视图事件或者外部测试用例发出 Action,经由 Dispatcher 派发给 StoreStore 会触发相应的方法更新数据、更新视图
  • Store 可以有多个
  • Store 不仅存放数据,还封装了处理数据的方法

Vuex#

VuexVue 官方推出的状态管理库。

Vuex 的核心概念:

  • Store: Vuex 采用单一状态树,每个应用仅有一个 Store 实例,在该实例下包含了 state、actions、mutations、getters、modules
  • State: Vuex 为单一数据源。可以通过 mapState 辅助函数将 state 作为计算属性访问,或者将通过 Storestate 注入全局之后使用 this.$store.state 访问。State 更新视图是通过 vue 的双向绑定机制实现的。
  • Getter: Getter 的作用与 filters 有一些相似,可以将 State 进行过滤后输出。
  • Mutation: Mutaionvuex 中改变 State 的唯一途径(严格模式下),并且只能是同步操作。Vuex 中通过 store.commit( ) 调用 Mutation
  • Action: 一些对 State 的异步操作可以放在 Action 中,并通过在 Action 提交 Mutaion 变更状态。Action 通过 store.dispatch( ) 方法触发。可以通过 mapActions 辅助函数将 vue 组件的 methods 映射成 store.dispatch 调用(需要先在根节点注入 store)。
  • Module: 当 Store 对象过于庞大时,可根据具体的业务需求分为多个 Module,每个 Module 都具有自己的 state 、mutation 、action 、getter

image-20220627105636282

Vuex 的特点:

  • 单向数据流。View 通过 store.dispatch( ) 调用 Action,在 Action 执行完异步操作之后通过 store.commit( ) 调用 Mutation 更新 State,通过 vue 的响应式机制进行视图更新。
  • 单一数据源,和 Redux 一样全局只有一个 Store 实例。
  • 可直接对 State 进行修改。

Redux#

作为一款针对 JavaScript 应用的可预测状态管理容器库,由 Dan Abramov2015 年创建的 Redux 在创建之初曾受到 Flux 架构以及函数式 Elm 的启发。后来,随着 Dan Abramov 加盟 FacebookRedux 最终成为 Facebook 旗下的一个子项目。Redux 之所以被广泛接受,是因为 Redux 融合了各家技术于一身,不但简化了 Flux 的流程与开发方式,还引入了一些优秀的设计理念。

作为一个应用状态管理库,ReduxFlux 有很多相似的地方。不同之处在于,Flux 可以有很多个改变应用状态的 Store,并可以通过事件来触发状态的变化,组件可以通过订阅这些事件来和当前状态保持同步。

Redux 中,则并没有 Dispatcher(分发器)的概念,Redux 使用一个单独的常量状态树来保存整个应用的状态,并且这个对象是不能直接被改变的。如果某些数据发生改变,那么就会创建出一个新的对象。

由于 Redux 是在 Flux 的基础上扩展出的一种单向数据流的实现,所以数据的流向、变化都能得到清晰的控制,并且能很好地划分业务逻辑和视图逻辑。

Redux 的组成:

  • Store: 存储应用 state 以及用于触发 state 更新的 dispatch 方法等,整个应用仅有单一的 Store
  • Store 中提供了几个 API:
    • store.getState( ): 获取当前 state
    • store.dispatch(action): 用于 View 发出 Action
    • store.subscribe(listener): 设置监听函数,一旦 state 变化则执行该函数(若把视图更新函数作为 listener 传入,则可触发视图自动渲染)。
  • Action: 同 FluxAction 是用于更新 state 的消息对象,由 View 发出。有专门生成 ActionAction Creator
  • Reducer: 是一个用于改变 state 的纯函数(对于相同的参数返回相同的返回结果,不修改参数,不依赖外部变量),即通过应用状态与 Action 推导出新的 state: (previousState, action) => newStateReducer 返回一个新的 state

image-20220627110106329

Redux 的特点:

  • 单向数据流。View 发出 Action(store.dispatch(action))Store 调用 Reducer 计算出新的 state,若 state 产生变化,则调用监听函数重新渲染 View (store.subscribe(render))
  • 单一数据源,只有一个 Store
  • state 是只读的,每次状态更新之后只能返回一个新的 state
  • 没有 Dispatcher,而是在 Store 中集成了 dispatch 方法,store.dispatch( )View 发出 Action 的唯一途径。

Mobx#

作为一个应用状态管理库,Redux 被广泛用于复杂的大型应用中,在很多大型 Web 前端应用中都可以看到它的身影。不过除了 Redux,社区里近年来还有另一产品呼声很高,那就是 Mobx

MobX 是由 Mendix、CoinbaseFacebook 开源的状态管理框架。MobX 背后的哲学是:

任何源自应用状态的东西都应该自动地获得。

意思就是,当状态改变时,所有应用到状态的地方都会自动更新。它通过响应式函数编程来实现状态的存储和管理。受到面向对象编程和响应式编程的影响,Mobx 可以将状态包装成可观察对象,通过观察和修改对象的状态进而实现视图的更新。

这样一个功能强大,上手非常容易的状态管理工具。就连 Redux 的作者也曾经向大家推荐过它,在不少情况下你的确可以使用 Mobx 来替代掉 Redux

MobX 的核心概念:

  • State: 驱动应用的数据
  • Computed values: 计算值。如果你想创建一个基于当前状态的值时,请使用 computed
  • Reactions: 反应,当状态改变时自动发生
  • Actions: 动作,用于改变 State
  • 依赖收集(autoRun): MobX 中的数据以来基于观察者模式,通过 autoRun 方法添加观察者

image-20220627110125184

MobX 的特点:

  • 数据流流动不自然,只有用到的数据才会引发绑定,局部精确更新(细粒度控制)
  • 没有时间回溯能力,因为数据只有一份引用
  • 基于面向对象
  • 往往是多个 Store
  • 代码侵入性小
  • 简单可扩展
  • 大型项目使用 MobX 会使得代码难以维护

最后总结一下:

  • Flux 、Redux 、Vuex 均为单向数据流。
  • ReduxVuex 是基于 Flux 的,Redux 较为泛用,Vuex 只能用于 vue
  • FluxMobX 可以有多个 StoreRedux、Vuex 全局仅有一个 Store(单状态树)。
  • Redux、Vuex 适用于大型项目的状态管理,MobX 在大型项目中应用会使代码可维护性变差。
  • Redux 中引入了中间件,主要解决异步带来的副作用,可通过约定完成许多复杂工作。
  • MobX 是状态管理库中代码侵入性最小的之一,具有细粒度控制、简单可扩展等优势,但是没有时间回溯能力,一般适合应用于中小型项目中。