makeObservable #
makeObservable 是 MobX 提供的一个函数,用于在类中显式地标记哪些属性是可观察的、哪些方法是动作、哪些属性是计算值。
基本用法 #
简单示例 #
javascript
import { makeObservable, observable, action, computed } from 'mobx';
class Counter {
// 可观察状态
count = 0;
constructor() {
// 配置响应式
makeObservable(this, {
count: observable,
increment: action,
decrement: action,
double: computed
});
}
// 动作
increment() {
this.count++;
}
decrement() {
this.count--;
}
// 计算值
get double() {
return this.count * 2;
}
}
注解类型 #
MobX 提供了多种注解类型:
observable #
标记属性为可观察状态:
javascript
import { makeObservable, observable } from 'mobx';
class Store {
constructor() {
makeObservable(this, {
// 基本类型
count: observable,
name: observable,
// 对象
user: observable,
// 数组
items: observable
});
}
count = 0;
name = '';
user = {};
items = [];
}
observable的变体 #
javascript
import { makeObservable, observable } from 'mobx';
class Store {
constructor() {
makeObservable(this, {
// 深度观察(默认)
deepObject: observable,
// 浅层观察
shallowArray: observable.shallow,
// 引用观察
refValue: observable.ref,
// 结构观察
structValue: observable.struct
});
}
deepObject = { nested: { value: 1 } };
shallowArray = [{ id: 1 }];
refValue = { data: 'test' };
structValue = { x: 0, y: 0 };
}
action #
标记方法为动作:
javascript
import { makeObservable, observable, action } from 'mobx';
class Store {
count = 0;
constructor() {
makeObservable(this, {
count: observable,
increment: action,
decrement: action,
reset: action.bound // 自动绑定this
});
}
increment() {
this.count++;
}
decrement() {
this.count--;
}
reset() {
this.count = 0;
}
}
action.bound #
自动绑定 this:
javascript
import { makeObservable, observable, action } from 'mobx';
class Store {
count = 0;
constructor() {
makeObservable(this, {
count: observable,
increment: action.bound
});
}
increment() {
this.count++;
}
}
const store = new Store();
const { increment } = store;
increment(); // this 正确绑定
computed #
标记 getter 为计算值:
javascript
import { makeObservable, observable, computed } from 'mobx';
class TodoStore {
todos = [];
constructor() {
makeObservable(this, {
todos: observable,
completedCount: computed,
activeCount: computed,
totalCount: computed
});
}
get completedCount() {
return this.todos.filter(t => t.completed).length;
}
get activeCount() {
return this.todos.filter(t => !t.completed).length;
}
get totalCount() {
return this.todos.length;
}
}
computed的变体 #
javascript
import { makeObservable, observable, computed } from 'mobx';
class Store {
position = { x: 0, y: 0 };
constructor() {
makeObservable(this, {
position: observable,
// 结构比较,避免不必要的更新
normalizedPosition: computed.struct
});
}
get normalizedPosition() {
return {
x: this.position.x / 100,
y: this.position.y / 100
};
}
}
override #
覆盖继承的属性:
javascript
import { makeObservable, observable, action, override } from 'mobx';
class BaseStore {
count = 0;
constructor() {
makeObservable(this, {
count: observable,
increment: action
});
}
increment() {
this.count++;
}
}
class ExtendedStore extends BaseStore {
constructor() {
super();
makeObservable(this, {
increment: override // 覆盖父类方法
});
}
increment() {
this.count += 2; // 不同的实现
}
}
完整示例 #
Todo Store #
javascript
import { makeObservable, observable, action, computed } from 'mobx';
class TodoStore {
// 状态
todos = [];
filter = 'all';
constructor() {
makeObservable(this, {
// 状态
todos: observable,
filter: observable,
// 动作
addTodo: action,
removeTodo: action,
toggleTodo: action,
setFilter: action.bound,
clearCompleted: action,
// 计算值
filteredTodos: computed,
completedCount: computed,
activeCount: computed
});
}
// 动作
addTodo(title) {
this.todos.push({
id: Date.now(),
title,
completed: false
});
}
removeTodo(id) {
this.todos = this.todos.filter(t => t.id !== id);
}
toggleTodo(id) {
const todo = this.todos.find(t => t.id === id);
if (todo) {
todo.completed = !todo.completed;
}
}
setFilter(filter) {
this.filter = filter;
}
clearCompleted() {
this.todos = this.todos.filter(t => !t.completed);
}
// 计算值
get filteredTodos() {
switch (this.filter) {
case 'completed':
return this.todos.filter(t => t.completed);
case 'active':
return this.todos.filter(t => !t.completed);
default:
return this.todos;
}
}
get completedCount() {
return this.todos.filter(t => t.completed).length;
}
get activeCount() {
return this.todos.length - this.completedCount;
}
}
export default new TodoStore();
用户 Store #
javascript
import { makeObservable, observable, action, computed, flow } from 'mobx';
class UserStore {
users = [];
currentUser = null;
loading = false;
error = null;
constructor() {
makeObservable(this, {
// 状态
users: observable,
currentUser: observable,
loading: observable,
error: observable,
// 动作
setUser: action,
clearUser: action,
setLoading: action.bound,
setError: action,
// 异步动作
fetchUsers: flow,
login: flow,
// 计算值
isLoggedIn: computed,
userCount: computed
});
}
// 同步动作
setUser(user) {
this.currentUser = user;
this.error = null;
}
clearUser() {
this.currentUser = null;
}
setLoading(loading) {
this.loading = loading;
}
setError(error) {
this.error = error;
}
// 异步动作(使用 flow)
*fetchUsers() {
this.loading = true;
try {
const response = yield fetch('/api/users');
const users = yield response.json();
this.users = users;
this.error = null;
} catch (error) {
this.error = error.message;
} finally {
this.loading = false;
}
}
*login(credentials) {
this.loading = true;
try {
const response = yield fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials)
});
const user = yield response.json();
this.currentUser = user;
this.error = null;
} catch (error) {
this.error = error.message;
} finally {
this.loading = false;
}
}
// 计算值
get isLoggedIn() {
return this.currentUser !== null;
}
get userCount() {
return this.users.length;
}
}
export default new UserStore();
使用装饰器(可选) #
如果你配置了装饰器支持,可以使用更简洁的语法:
javascript
import { observable, action, computed, makeObservable } from 'mobx';
class Store {
@observable count = 0;
@observable name = '';
@action
increment() {
this.count++;
}
@action.bound
reset() {
this.count = 0;
}
@computed
get double() {
return this.count * 2;
}
constructor() {
makeObservable(this);
}
}
makeObservable vs makeAutoObservable #
| 特性 | makeObservable | makeAutoObservable |
|---|---|---|
| 配置方式 | 显式配置 | 自动推断 |
| 灵活性 | 高 | 中 |
| 代码量 | 多 | 少 |
| 继承支持 | 好 | 有限 |
javascript
// makeObservable - 显式配置
class Store1 {
count = 0;
constructor() {
makeObservable(this, {
count: observable,
increment: action
});
}
increment() { this.count++; }
}
// makeAutoObservable - 自动推断
class Store2 {
count = 0;
constructor() {
makeAutoObservable(this);
}
increment() { this.count++; }
}
总结 #
makeObservable 提供了精细的响应式配置控制:
| 注解 | 用途 |
|---|---|
observable |
可观察状态 |
observable.shallow |
浅层观察 |
observable.ref |
引用观察 |
action |
动作方法 |
action.bound |
自动绑定this |
computed |
计算值 |
computed.struct |
结构比较的计算值 |
override |
覆盖继承成员 |
继续学习 makeAutoObservable,了解更简洁的自动配置方式。
最后更新:2026-03-28