在 MobX 中,observable 是核心概念之一,它将普通的 JavaScript 对象、数组、Map、Set 等数据结构转换为可观察对象,使 MobX 能够追踪其变化。
Observable 的使用方式
1. 使用装饰器(Decorator)
javascriptimport { observable, action, computed } from 'mobx'; class TodoStore { @observable todos = []; @observable filter = 'all'; @computed get completedTodos() { return this.todos.filter(todo => todo.completed); } @action addTodo(text) { this.todos.push({ text, completed: false }); } }
2. 使用 makeObservable
javascriptimport { makeObservable, observable, action, computed } from 'mobx'; class TodoStore { todos = []; filter = 'all'; constructor() { makeObservable(this, { todos: observable, filter: observable, completedTodos: computed, addTodo: action }); } get completedTodos() { return this.todos.filter(todo => todo.completed); } addTodo(text) { this.todos.push({ text, completed: false }); } }
3. 使用 makeAutoObservable(推荐)
javascriptimport { makeAutoObservable } from 'mobx'; class TodoStore { todos = []; filter = 'all'; constructor() { makeAutoObservable(this); } get completedTodos() { return this.todos.filter(todo => todo.completed); } addTodo(text) { this.todos.push({ text, completed: false }); } }
4. 使用 observable 函数
javascriptimport { observable } from 'mobx'; const state = observable({ todos: [], filter: 'all' }); const completedTodos = observable(() => state.todos.filter(todo => todo.completed) );
Observable 的特性
1. 自动追踪依赖
当 observable 对象被读取时,MobX 会自动建立依赖关系。
javascriptimport { observable, autorun } from 'mobx'; const store = observable({ count: 0 }); autorun(() => { console.log('Count is:', store.count); }); store.count = 1; // 自动触发 autorun
2. 深度可观察
observable 默认是深度可观察的,会递归地将对象的所有属性都转换为可观察。
javascriptconst store = observable({ user: { name: 'John', address: { city: 'New York' } } }); store.user.address.city = 'Boston'; // 会被追踪
3. 数组和 Map 的特殊处理
observable 数组和 Map 提供了额外的 API,但保持与原生 API 兼容。
javascriptconst list = observable([1, 2, 3]); list.push(4); // MobX 会追踪这个变化 list.splice(0, 1); // 也会被追踪
Observable 配置选项
1. shallow(浅层可观察)
只追踪对象本身的变化,不追踪嵌套对象。
javascriptimport { observable } from 'mobx'; const store = observable({ user: { name: 'John' } }, {}, { deep: false }); store.user = { name: 'Jane' }; // 会被追踪 store.user.name = 'Bob'; // 不会被追踪
2. asMap、asArray
显式指定数据结构类型。
javascriptconst map = observable.map({ key: 'value' }); const array = observable.array([1, 2, 3]);
注意事项
- 不要在 action 外部修改 observable 状态
- 避免在 constructor 中使用装饰器
- 合理使用 computed 缓存计算结果
- 对于大型对象,考虑使用 shallow 优化性能
- observable 对象不能被冻结(Object.freeze)
最佳实践
- 优先使用
makeAutoObservable简化配置 - 对于简单状态,使用
observable函数 - 对于复杂状态管理,使用类 + 装饰器或
makeObservable - 合理使用 computed 避免重复计算
- 始终在 action 中修改 observable 状态