Skip to main content

MobX 原理

状态管理总览见状态管理。这里补 MobX:可变数据 + 响应式依赖收集

一句话

改普通对象字段,依赖这些字段的视图/计算 自动 更新——靠的是运行时的 可观察(observable)+ 依赖追踪,不是靠你手写 immutable reducer。

和 zustand / redux 的对比(面试常问)

MobXzustandredux
数据默认mutable更新时浅合并出新状态immutable
订阅粒度读到的属性级(典型)选择器函数通常 connect/选择器
心智OOP / 响应式极简 hook storeaction → reducer
样板中等(decorator/makeObservable)很少相对多

选型直觉:要「改字段就刷新、模型感强」→ MobX;要「API 最少、函数式一点点」→ zustand。

核心概念

  1. Observable state — 被追踪的状态
  2. Computed — 从 state 派生,有缓存
  3. Reaction — 副作用:autorun、React 里的 observer
  4. 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 即可):

  1. 可观察属性时:当前正在执行的 reaction(比如 observer 组件的一次渲染)被记录为依赖
  2. 属性时:通知依赖了该属性的 reaction 调度更新
  3. 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-liteobserver
  • 不要过早解构:const { count } = store 若在 observer 外或丢了响应式包装,可能丢追踪(读的时候要在 observer 组件渲染路径上)
  • 本地 UI 状态仍可用 useState;跨组件领域模型放 store

面试速答清单

  1. MobX 怎么做到改数据就更新视图? → 可观察 + 渲染期依赖收集 + 写入时通知。
  2. 和 Redux 最大差异? → 可变 vs 不可变;自动追踪 vs 显式订阅/选择器。
  3. computed 有什么用? → 派生数据缓存,依赖不变不重算。
  4. 为什么要 action? → 聚合修改、批量通知、可维护与严格模式约束。
  5. 何时选 MobX? → 复杂可变领域模型、想少写样板订阅;小项目 / 偏函数式团队更常 zustand。

相关:状态管理