MobX 原理
状态管理总览见状态管理。这里补 MobX:可变数据 + 响应式依赖收集。
一句话
改普通对象字段,依赖这些字段的视图/计算 自动 更新——靠的是运行时的 可观察(observable)+ 依赖追踪,不是靠你手写 immutable reducer。
和 zustand / redux 的对比( 面试常问)
| MobX | zustand | redux | |
|---|---|---|---|
| 数据默认 | mutable | 更新时浅合并出新状态 | immutable |
| 订阅粒度 | 读到的属性级(典型) | 选择器函数 | 通常 connect/选择器 |
| 心智 | OOP / 响应式 | 极简 hook store | action → reducer |
| 样板 | 中等(decorator/makeObservable) | 很少 | 相对多 |
选型直觉:要「改字段就刷新、模型感强」→ MobX;要「API 最少、函数式一点点」→ zustand。
核心概念
- Observable state — 被追踪的状态
- Computed — 从 state 派生,有缓存
- Reaction — 副作用:
autorun、React 里的observer - Action — 修改 state 的入口(严格模式下建议所有修改走 action)
import { makeAutoObservable } from 'mobx'
class CounterStore {
count = 0
constructor() {
makeAutoObservable(this)
}
get double() {
return this.count * 2 // computed
}
inc() {
this.count++ // action
}
}
export const counterStore = new CounterStore()
import { observer } from 'mobx-react-lite'
const CounterView = observer(function CounterView() {
return (
<button type="button" onClick={() => counterStore.inc()}>
{counterStore.count} / {counterStore.double}
</button>
)
})
observer 包过的组件:渲染时读到哪些可观察字段,就订阅哪些;字段变了才重渲染。
原理直觉(Proxy / 依赖收集)
现代 MobX 大量基于 Proxy(也有旧的 defineProperty 路径,面试提 Proxy 即可):
- 读 可观察属性时:当前正在执行的 reaction(比如
observer组件的一次渲染)被记录为依赖 - 写 属性时:通知依赖了该属性的 reaction 调度更新
- computed:第一次算时收集依赖;依赖不变则返回缓存
可以和 Vue 的依赖收集类比,但落地在「任意 JS 对象模型 + React observer」上。
组件 render(reaction 激活)
→ 读 store.count(收集依赖)
→ render 结束,订阅关系固定
之后 store.count 变更
→ 触发该 reaction
→ 组件再 render
Action 与批量
多次改字段时,MobX 会把同一 action / 同一事件循环里的更新尽量 批处理,避免改一下刷一次。
import { runInAction } from 'mobx'
async function load() {
const data = await fetch('/api').then((r) => r.json())
runInAction(() => {
store.list = data.list
store.loading = false
})
}
异步回调里改状态,常用 runInAction(或 flow),面试可提「严格模式不允许在 action 外改 observable」。
和 React 集成要点
- 函数组件用
mobx-react-lite的observer - 不要过早解构:
const { count } = store若在 observer 外或丢了响应式包装,可能丢追踪(读的时候要在 observer 组件渲染路径上) - 本地 UI 状态仍可用
useState;跨组件领域模型放 store
面试速答清单
- MobX 怎么做到改数据就更新视图? → 可观察 + 渲染期依赖收集 + 写入时通知。
- 和 Redux 最大差异? → 可变 vs 不可变;自动追踪 vs 显式订阅/选择器。
- computed 有什么用? → 派生数据缓存,依赖不变不重算。
- 为什么要 action? → 聚合修改、批量通知、可维护与严格模式约束。
- 何时选 MobX? → 复杂可变领域模型、想少写样板订阅;小项目 / 偏函数式团队更常 zustand。
相关:状态管理