基本理论
通过 响应式编程 的方式管理应用状态。 思想:任何可以从应用状态中派生出来的值都应该自动派生
| 能力 | 覆盖情况 |
|---|---|
| 基础原理 | 响应式核心思想、三大核心概念(State/Actions/Derivations) |
| Store 构建 | 类方式 / 函数方式创建 Store、makeAutoObservable 简化配置 |
| 核心响应式 API | Observable(状态)、Action(修改)、Computed(计算)、Reaction(副作用) |
| React 集成 | observer 高阶组件、多 Store 管理、Context Provider 模式 |
| 异步处理 | 异步 Action、runInAction 批量更新(解决异步状态更新问题) |
| 复杂状态支持 | 嵌套 Observable、数组 / Map/Set 响应式操作 |
- State(状态) :应用的数据
- Actions(动作) :修改状态的操作
- Derivations(派生) :从状态中自动计算出的值(Computed)和副作用(Reactions)
数据流
基本使用
安装
npm install mobx mobx-react-lite
# 或使用 mobx-react(支持类组件)
npm install mobx mobx-react
创建 Store(类方式)
import { makeAutoObservable } from 'mobx'
class CounterStore {
count = 0
constructor() {
// makeAutoObservable 会自动将类的属性和方法转换为 observable 和 action
makeAutoObservable(this)
}
increment() {
this.count++
}
decrement() {
this.count--
}
reset() {
this.count = 0
}
// 计算属性(computed)
get doubleCount() {
return this.count * 2
}
}
// 创建 store 实例
const counterStore = new CounterStore()
export default counterStore
创建 Store(函数方式)
import { makeAutoObservable } from 'mobx'
function createCounterStore() {
return makeAutoObservable({
count: 0,
increment() {
this.count++
},
decrement() {
this.count--
},
reset() {
this.count = 0
},
get doubleCount() {
return this.count * 2
},
})
}
const counterStore = createCounterStore()
export default counterStore
在组件中使用
import { observer } from 'mobx-react-lite'
import counterStore from './stores/counterStore'
// observer 高阶组件使组件能够响应 observable 的变化
const Counter = observer(() => {
return (
<div>
<button onClick={() => counterStore.decrement()}>-</button>
<span>{counterStore.count}</span>
<button onClick={() => counterStore.increment()}>+</button>
<p>Double: {counterStore.doubleCount}</p>
</div>
)
})
export default Counter
核心 API
Observable(可观察状态)
Observable 是 MobX 的核心,用于创建可观察的状态。
import { observable, makeObservable } from 'mobx'
class Store {
count = 0
name = 'MobX'
constructor() {
makeObservable(this, {
count: observable,
name: observable,
})
}
}
Action(动作)
Action 是修改状态的操作。MobX 要求所有修改状态的操作都应该在 action 中。
import { action, makeObservable } from 'mobx'
class Store {
count = 0
constructor() {
makeObservable(this, {
count: observable,
increment: action,
decrement: action,
})
}
increment() {
this.count++ // 在 action 中修改状态
}
decrement() {
this.count--
}
}
Computed(计算值)
Computed 是从状态中自动计算出的值,只有当依赖的状态变化时才会重新计算。
import { computed, makeObservable } from 'mobx'
class Store {
count = 0
constructor() {
makeObservable(this, {
count: observable,
doubleCount: computed, // 计算属性
})
}
get doubleCount() {
return this.count * 2 // 自动追踪 count 的变化
}
}
Reaction(副作用)
Reaction 是响应状态变化的副作用,如日志记录、网络请求等。
import { reaction, autorun, when } from 'mobx'
// autorun:自动运行,立即执行一次
autorun(() => {
console.log('Count changed:', store.count)
})
// reaction:响应特定状态变化
reaction(
() => store.count, // 追踪的状态
(count) => {
console.log('Count is now:', count)
}
)
// when:条件满足时执行
when(
() => store.count > 10, // 条件
() => {
console.log('Count is greater than 10!')
}
)
makeAutoObservable
makeAutoObservable 是最简单的方式,它会自动将类的属性和方法转换为 observable 和 action。
import { makeAutoObservable } from 'mobx'
class Store {
count = 0 // 自动变为 observable
name = 'MobX' // 自动变为 observable
increment() { // 自动变为 action
this.count++
}
get doubleCount() { // 自动变为 computed
return this.count * 2
}
constructor() {
makeAutoObservable(this)
}
}
在 React 中使用MobX
observer 高阶组件
observer 是 MobX 与 React 集成的核心,它使组件能够响应 observable 的变化。
import { observer } from 'mobx-react-lite'
import counterStore from './stores/counterStore'
const Counter = observer(() => {
return (
<div>
<span>{counterStore.count}</span>
<button onClick={() => counterStore.increment()}>+</button>
</div>
)
})
使用多个 Store
import { observer } from 'mobx-react-lite'
import counterStore from './stores/counterStore'
import todoStore from './stores/todoStore'
const App = observer(() => {
return (
<div>
<Counter />
<TodoList />
</div>
)
})
Provider 模式(可选)
MobX 也支持 Provider 模式,通过 Context 传递 store:
import { createContext, useContext } from 'react'
import { observer } from 'mobx-react-lite'
import counterStore from './stores/counterStore'
const StoreContext = createContext(counterStore)
function App() {
return (
<StoreContext.Provider value={counterStore}>
<Counter />
</StoreContext.Provider>
)
}
const Counter = observer(() => {
const store = useContext(StoreContext)
return <div>{store.count}</div>
})
异步操作
MobX 天然支持异步操作,无需额外配置:
import { makeAutoObservable, runInAction } from 'mobx'
class UserStore {
users = []
loading = false
error = null
constructor() {
makeAutoObservable(this)
}
async fetchUsers() {
this.loading = true
this.error = null
try {
const response = await fetch('/api/users')
const users = await response.json()
// 在异步操作中修改状态,需要使用 runInAction
runInAction(() => {
this.users = users
this.loading = false
})
} catch (error) {
runInAction(() => {
this.error = error.message
this.loading = false
})
}
}
}
runInAction
runInAction 用于在异步操作中批量更新状态,确保所有更新都在同一个事务中:
import { runInAction } from 'mobx'
async function fetchData() {
runInAction(() => {
store.loading = true
store.error = null
})
try {
const data = await api.getData()
runInAction(() => {
store.data = data
store.loading = false
})
} catch (error) {
runInAction(() => {
store.error = error.message
store.loading = false
})
}
}
其他高级特性
嵌套 Observable
MobX 支持嵌套的 observable 对象和数组:
import { makeAutoObservable } from 'mobx'
class TodoStore {
todos = []
constructor() {
makeAutoObservable(this)
}
addTodo(text) {
this.todos.push({
id: Date.now(),
text,
completed: false,
})
}
toggleTodo(id) {
const todo = this.todos.find(t => t.id === id)
if (todo) {
todo.completed = !todo.completed // 嵌套对象的属性也是 observable
}
}
}
数组操作
MobX 提供了 observable 数组,支持所有原生数组方法:
import { observable } from 'mobx'
const todos = observable([{ id: 1, text: 'Learn MobX' }])
// 所有数组操作都是响应式的
todos.push({ id: 2, text: 'Build app' })
todos[0].text = 'Learn MobX deeply'
todos.splice(0, 1)
Map 和 Set
MobX 也支持 observable Map 和 Set:
import { observable } from 'mobx'
const userMap = observable.map({})
userMap.set('user1', { name: 'John' })
const userIds = observable.set([1, 2, 3])
userIds.add(4)
自定义 Reaction
import { reaction } from 'mobx'
// 自定义 reaction,响应特定状态变化
const dispose = reaction(
() => store.count, // 追踪的状态
(count) => {
console.log('Count changed to:', count)
// 执行副作用
}
)
// 清理 reaction
dispose()
补充
调试工具
import { enableLogging, trace } from 'mobx'
// 1. 开启 MobX 日志(仅开发环境)
if (process.env.NODE_ENV === 'development') {
enableLogging({ level: 'info', name: 'TodoStore' })
}
class TodoStore {
addTodo = (text) => {
// 2. 追踪单个 Action 的状态变化
trace(this, 'addTodo')
this.todos.push({ id: Date.now(), text, completed: false })
}
}
// 3. Chrome 扩展:MobX DevTools(可视化监控 Observable/Action 变化)