工具函数 #
MobX 提供了一系列实用工具函数,帮助开发者更好地处理可观察状态、调试和类型检查。
toJS #
将可观察对象转换为普通 JavaScript 对象。
基本用法 #
javascript
import { makeAutoObservable, toJS } from 'mobx';
class Store {
items = [{ name: 'Item 1' }, { name: 'Item 2' }];
user = { name: 'John', age: 30 };
constructor() {
makeAutoObservable(this);
}
}
const store = new Store();
// 转换为普通对象
const plainItems = toJS(store.items);
const plainUser = toJS(store.user);
console.log(plainItems);
// [{ name: 'Item 1' }, { name: 'Item 2' }]
console.log(plainUser);
// { name: 'John', age: 30 }
使用场景 #
javascript
import { toJS } from 'mobx';
// 1. 发送到服务器
async function saveData() {
const plainData = toJS(store.data);
await fetch('/api/save', {
method: 'POST',
body: JSON.stringify(plainData)
});
}
// 2. 深拷贝
const copy = toJS(store.complexObject);
// 3. 比较
const isEqual = JSON.stringify(toJS(obj1)) === JSON.stringify(toJS(obj2));
// 4. 日志
console.log('State:', toJS(store));
isObservable #
检查对象是否为可观察对象。
基本用法 #
javascript
import { isObservable, makeAutoObservable, observable } from 'mobx';
const plainObject = { count: 0 };
const observableObject = observable({ count: 0 });
console.log(isObservable(plainObject)); // false
console.log(isObservable(observableObject)); // true
相关检查函数 #
javascript
import {
isObservable,
isObservableObject,
isObservableArray,
isObservableMap,
isObservableSet,
isBoxedObservable,
isObservableProp,
isComputed,
isAction,
makeAutoObservable
} from 'mobx';
class Store {
items = [];
user = new Map();
tags = new Set();
get count() {
return this.items.length;
}
addItem() {
this.items.push({});
}
constructor() {
makeAutoObservable(this);
}
}
const store = new Store();
// 检查整体
isObservable(store); // true
// 检查类型
isObservableObject(store); // true
isObservableArray(store.items); // true
isObservableMap(store.user); // true
isObservableSet(store.tags); // true
// 检查属性
isObservableProp(store, 'items'); // true
isComputed(store, 'count'); // true
isAction(store, 'addItem'); // true
extendObservable #
向现有对象添加可观察属性。
基本用法 #
javascript
import { extendObservable } from 'mobx';
const user = { name: 'John' };
// 添加可观察属性
extendObservable(user, {
age: 30,
get displayName() {
return `${this.name} (${this.age})`;
}
});
user.age = 31; // 响应式更新
使用场景 #
javascript
import { extendObservable, autorun } from 'mobx';
// 动态添加属性
class DynamicStore {
constructor() {
extendObservable(this, {
count: 0,
increment() {
this.count++;
}
});
}
}
const store = new DynamicStore();
autorun(() => {
console.log('Count:', store.count);
});
store.increment();
observable.box #
创建可观察的基本类型值。
基本用法 #
javascript
import { observable, autorun } from 'mobx';
const count = observable.box(0);
const name = observable.box('MobX');
// 读取
console.log(count.get()); // 0
console.log(name.get()); // 'MobX'
// 修改
count.set(1);
name.set('MobX 6');
// 响应式
autorun(() => {
console.log('Count:', count.get());
});
count.set(2); // 输出: Count: 2
使用场景 #
javascript
import { observable, computed } from 'mobx';
// 简单状态
const loading = observable.box(false);
// 切换状态
function toggleLoading() {
loading.set(!loading.get());
}
// 计算值
const status = computed(() => loading.get() ? 'Loading...' : 'Ready');
// 观察变化
import { observe } from 'mobx';
observe(loading, (change) => {
console.log(`Loading changed from ${change.oldValue} to ${change.newValue}`);
});
observe #
观察可观察对象的变化。
基本用法 #
javascript
import { observe, makeAutoObservable } from 'mobx';
class Store {
count = 0;
items = [];
constructor() {
makeAutoObservable(this);
}
}
const store = new Store();
// 观察属性变化
const dispose = observe(store, 'count', (change) => {
console.log(`count: ${change.oldValue} -> ${change.newValue}`);
});
store.count = 1; // 输出: count: 0 -> 1
// 清除观察
dispose();
观察数组变化 #
javascript
import { observe, observable } from 'mobx';
const items = observable([1, 2, 3]);
observe(items, (change) => {
console.log('Array changed:', change);
// change.type: 'splice' | 'update'
// change.added: 添加的元素
// change.removed: 删除的元素
// change.index: 变化的索引
});
items.push(4); // 触发观察
观察Map变化 #
javascript
import { observe, observable } from 'mobx';
const map = observable.map({ a: 1 });
observe(map, (change) => {
console.log('Map changed:', change);
// change.type: 'add' | 'update' | 'delete'
// change.name: 键名
// change.newValue: 新值
// change.oldValue: 旧值
});
map.set('b', 2); // 触发观察
computed和autorun的变体 #
computed.struct #
结构比较的计算值:
javascript
import { computed, makeAutoObservable } from 'mobx';
class Store {
x = 0;
y = 0;
constructor() {
makeAutoObservable(this, {
position: computed.struct
});
}
get position() {
return { x: this.x, y: this.y };
}
}
const store = new Store();
// 普通 computed:每次返回新对象,会触发更新
// computed.struct:结构相同则不触发更新
store.x = 0; // position 返回 { x: 0, y: 0 }
store.x = 0; // position 仍返回 { x: 0, y: 0 },不触发更新
autorun的选项 #
javascript
import { autorun } from 'mobx';
// 延迟执行
autorun(
() => {
console.log(store.count);
},
{ delay: 300 } // 防抖
);
// 自定义调度器
autorun(
() => {
console.log(store.count);
},
{
scheduler: (run) => {
requestAnimationFrame(run);
}
}
);
// 设置名称(调试用)
autorun(
() => {
console.log(store.count);
},
{ name: 'countLogger' }
);
其他工具函数 #
transaction #
批量更新(已弃用,使用 action 替代):
javascript
import { transaction, makeAutoObservable } from 'mobx';
// 推荐使用 action
class Store {
a = 0;
b = 0;
constructor() {
makeAutoObservable(this);
}
updateBoth(a, b) {
this.a = a;
this.b = b;
// action 自动批量更新
}
}
untracked #
在追踪上下文中不追踪某些访问:
javascript
import { untracked, autorun, makeAutoObservable } from 'mobx';
class Store {
count = 0;
debug = true;
constructor() {
makeAutoObservable(this);
}
}
const store = new Store();
autorun(() => {
// 不追踪 debug 的变化
const shouldLog = untracked(() => store.debug);
if (shouldLog) {
console.log('Count:', store.count);
}
});
store.debug = false; // 不会触发 autorun
store.count = 1; // 会触发 autorun
spy #
全局监听所有 MobX 事件:
javascript
import { spy } from 'mobx';
// 启用全局监听
const dispose = spy((event) => {
if (event.type === 'action') {
console.log(`Action: ${event.name}`, event);
}
});
// 清除监听
dispose();
完整示例 #
调试工具 #
javascript
import { spy, toJS, isObservable } from 'mobx';
// 开发环境启用调试
if (process.env.NODE_ENV === 'development') {
spy((event) => {
if (event.type === 'action') {
console.group(`Action: ${event.name}`);
console.log('Arguments:', event.arguments);
console.log('Target:', event.target);
console.groupEnd();
}
});
}
// 状态快照
function getSnapshot(store) {
if (!isObservable(store)) {
return store;
}
return toJS(store);
}
// 状态比较
function compareState(store1, store2) {
return JSON.stringify(getSnapshot(store1)) === JSON.stringify(getSnapshot(store2));
}
持久化工具 #
javascript
import { toJS, autorun, makeAutoObservable } from 'mobx';
function persist(store, key, storage = localStorage) {
// 恢复状态
const saved = storage.getItem(key);
if (saved) {
try {
const data = JSON.parse(saved);
Object.assign(store, data);
} catch (e) {
console.error('Failed to restore state:', e);
}
}
// 自动保存
autorun(() => {
storage.setItem(key, JSON.stringify(toJS(store)));
});
}
// 使用
class UserStore {
name = '';
email = '';
constructor() {
makeAutoObservable(this);
persist(this, 'user-store');
}
}
总结 #
| 函数 | 用途 |
|---|---|
toJS |
转换为普通对象 |
isObservable |
检查是否可观察 |
extendObservable |
添加可观察属性 |
observable.box |
创建可观察基本值 |
observe |
观察变化 |
untracked |
不追踪访问 |
spy |
全局监听 |
继续学习 项目结构,了解 MobX 项目的最佳组织方式。
最后更新:2026-03-28