状态管理原理与设计

1. 为什么要使用状态管理?

如果你的应用足够简单,也许不需要。React 的 Context + useReducer 或者 Vue 的 provide/inject 就够了。 但在以下场景,建议引入状态管理:

  1. 多个视图依赖同一个状态:如右上角的购物车数量,需要在任何页面都能看到。
  2. 不同视图的行为需要变更同一个状态:如在商品详情页添加购物车,购物车页也要同步更新。
  3. 复杂的异步流程:如用户登录后,需要先鉴权,再拉取个人信息,再拉取消息列表,中间任何一步失败都要处理。
  4. 调试与快照:需要回放 Actions,排查 Bug。

2. 常见状态管理模式

(1) Flux 思想 (单向数据流)

最经典的设计原则。

  • Action:描述发生了什么(Type + Payload)。
  • Dispatcher:分发 Action。
  • Store:根据 Action 更新 State。
  • View:View 只能通过 Dispatch Action 来改变 State,永远不能直接修改 State
  • 优点:数据流清晰,便于追踪 Bug。

(2) Redux (基于 Flux)

React 生态的绝对霸主。

  • 单一数据源:整个应用只有一个 Store。
  • State 只读:只能通过 dispatch action 触发 reducer 去修改 state。
  • 纯函数 Reducer:reducer (state, action) => newState 必须是纯函数,不能有副作用(如 API 调用,必须在 middleware 中做)。
  • 缺点:样板代码极多(Action Types, Action Creators, Reducers...)。

(3) MobX (响应式)

完全不同的哲学:面向对象 + 响应式

  • 观察者模式:通过 makeAutoObservable 让对象的属性变成可观察的。
  • 自动追踪:当 Observable 变化时,自动更新所有使用了该属性的组件。
  • 可变状态:允许直接修改状态 store.count++
  • 优点:极其简洁,不需要写 reducer。性能极好(细粒度更新)。
  • 缺点:数据流不如 Redux 清晰,容易滋生混乱的代码(到处直接修改 store)。

(4) Vuex vs Pinia (Vue 生态)

Vuex (Vue 2 时代):

  • 核心概念:State, Getters, Mutations (同步), Actions (异步), Modules.
  • 痛点:TS 支持差,Mutation 必须是同步函数,代码较繁琐。

Pinia (Vue 3 官方推荐):

  • 去掉了 Mutation:现在只有 State, Getters, Actions。Action 可以是异步也可以是同步。
  • TypeScript 友好:极佳的类型推导。
  • 轻量:只有 1kb。
  • 模块化:每个 Store 都是独立的,不再挂载到一个复杂的树上。