MobX
- MobX 是一个简单、方便扩展、久经考验的状态管理解决方案
基本概念
- MobX 是一个独立的组件,可以配合各种框架使用,由于项目中需要使用 react & MobX。下面来详细了解一下
- State 是每一个应用程序的核心部分,而使用一个不合规范的 State 则是让你的应用充满 bug 和失控的不二法门,或者就是局部变量环绕,让你的 state 失去了同步。有很多框架试图解决这个问题,比如使用不可变的 state,但是这样以来又带来了新的问题,比如数据必须规格化,完整性约束失效等等。
MobX 功能
- MobX 让整个事情又变简单了:它不允许产生失控的 state。它的理念也很简单:所有可以从 state 中派生的事物,都会自动的派生。
- demo
class TodoStore {
todos = [];
get completedTodosCount() {
return this.todos.filter(
todo => todo.completed === true
).length;
}
report() {
if (this.todos.length === 0)
return "";
return `Next todo: "${this.todos[0].task}". `
`Progress: ${this.completedTodosCount}/${this.todos.length}`;
}
addTodo(task) {
this.todos.push({
task: task,
completed: false,
assignee: null
});
}
}
const todoStore = new TodoStore();
复制代码
代码语言:javascript复制当我们去创建一个
todoStore
,他拥有一个todos
集合,现在我们往这个todoStore
里添加一些东西,为了明显起见,就调用todoStore.report
todoStore.addTodo("read MobX tutorial");
console.log(todoStore.report());
todoStore.addTodo("try MobX");
console.log(todoStore.report());
todoStore.todos[0].completed = true;
console.log(todoStore.report());
todoStore.todos[1].task = "try MobX in own project";
console.log(todoStore.report());
todoStore.todos[0].task = "grok MobX tutorial";
console.log(todoStore.report());
- 太巧了,这就是 MobX 能为你做的事情。自动执行只在 state 改变的时候触发,就好像 Excel 中的图表只在单元格数据改变时更新一样。为了达到这个目标,
TodoStore
必须成为可观测的(observable
)才行,让我们来改一些代码。
observable & computed
代码语言:javascript复制同时,completedTodosCount 属性应该被自动派生,使用 @observable 和 @computed 装饰器来做这些事情:
class ObservableTodoStore {
@observable todos = [];
@observable pendingRequests = 0;
constructor() {
mobx.autorun(() => console.log(this.report));
}
@computed get completedTodosCount() {
return this.todos.filter(
todo => todo.completed === true
).length;
}
@computed get report() {
if (this.todos.length === 0)
return "";
return `Next todo: "${this.todos[0].task}". `
`Progress: ${this.completedTodosCount}/${this.todos.length}`;
}
addTodo(task) {
this.todos.push({
task: task,
completed: false,
assignee: null
});
}
}
const observableTodoStore = new ObservableTodoStore();
复制代码
- 在这个构造器中,我们使用
autorun
包裹了一个打出report
的小函数。Autorun
里的东西首先会运行一次,然后当其中的函数有observable
的数据发生变化时,会再次运行。 这里我们使用了todos
属性,每次todos
变化了我们就打印出新的东西。 - 测试一下
observableTodoStore.addTodo("read MobX tutorial");
observableTodoStore.addTodo("try MobX");
observableTodoStore.todos[0].completed = true;
observableTodoStore.todos[1].task = "try MobX in own project";
observableTodoStore.todos[0].task = "grok MobX tutorial";
举个栗子(sf 的一个问题有感)
- 对于单个对象,我可以使用computed通过计算获得一些属性,比如
@observable good = {
number: 2,
price: 3
}
@computed get totalPrice() {
return this.good.number * this.good.price;
}
// 数组
@observable goodsList = [{
number: 2,
price: 3
},{
number: 2,
price: 3
}]
- 问题?
- 这种情况我如何通过computed获得数组某个元素的计算属性呢,还是只能在改变number的函数中手动去更改,但是我数组的对象中并没有一个totalPrice的属性,每次把单个good push到goodsList中去还要给good添加一个totalPrice属性岂不是很麻烦
- 解决方案
- 把
good
弄成一个单独的model文件
- 把
export default class Good{
@observable number;
@observable price;
constructor(number, price) {
this.number = number;
this.price = price;
}
@computed
get totalPrice() {
return this.number * this.price
}
}
复制代码
-
- 然后在goodList文件中
- 这样就实现了自动计算, 访问的时候类似 this.props.goodList[0].totalPrice
@action
addGood(...args) {
this.todos.push(new Good(...args));
}
- 未完待续...
总结
- 最后总结一些:
@observale
修饰器或者 observable 函数让对象可以被追踪;@computed
修饰器创造了自动运算的表达式;autorun
函数让依靠 observable 的函数自动执行,这个用来写 log,发请求很不错;@observer
修饰器让React
组建自动起来,它会自动更新,即便是在一个很大的程序里也会工作的很好;MobX
不是一个状态容器
很多人把 MobX
当作另外一个 Redux
,但是它仅仅是一个库,不是一个什么架构。上面的例子还是需要程序员自己去组织逻辑和 store
或者控制器什么的.
引用:
10分钟极速入门 MobX
sf @computed使用
react 官网