mobx状态管理解决方案对标redux,mobx新手入门篇
发布于 作者:苏南大叔 来源:程序如此灵动~根据官方描述,MobX
是一种简单、可扩展并且身经百战的状态管理解决方案。它对标的是redux
。所以,官方描述中,也处处在针对redux
暗中做对比。“许多状态管理解决方案会——比如通过使状态不可变——试图限制你修改状态的方式。但这样就会引出新的问题:数据需要被归一化、引用的完整性无法得到保证。”
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:nodejs@20.18.0
,mobx@6.13.5
。本文只是在苏南大叔的视角来观察mobx
。mobx
和redux
一样,都可以独立使用。本文代码基于官方教程代码,略有修改。
官方入门教程
这个mobx
官方有个教程,号称“十分钟”就可以搞定mobx
。苏南大叔反正是反复看了好多个十分钟,还是云里雾里。
苏南大叔就分为两部分讲述对这个教程的理解。一个是普通的todolist
的需求写法,第二个是使用mobx
如何实现这个todolist
需求写法。至于mobx
和react
相结合的事情,到下一篇文章里面讲述。
加载mobx
根据不同的使用情况,可以选择不同的加载方式。
浏览器加载
可以选择别的地址加载mobx
,不过记得加载umd
版本的mobx.js
。
<script src="https://cdnjs.cloudflare.com/ajax/libs/mobx/6.13.5/mobx.umd.production.min.js"></script>
<script>
const { makeObservable, observable, computed, action, autorun } = mobx;
</script>
纯node加载
纯node
环境下加载的话,先安装再引入即可。
npm i mobx --save
const { makeObservable, observable, computed, action, autorun } = require("mobx");
import mbox, { makeObservable, observable, computed, action, autorun } from 'mobx';
需求说明
这个todoList
的类,需求就是个task
管理器。
- 一个
task
有两个属性,分别是task
(名字)、completed
(是否完成)。 task
管理器的.completedTodosCount
属性,就是统计一下有多少task
是被完成的。task
管理器的report()
属性,是用于整体统计的。包括:下一个未完成的任务、任务进度:任务完成数/任务总数。
mobx版todolist(响应式)
这个响应式的mbox
版本的todolist
,该如何编写代码呢?
const { makeObservable, observable, computed, action, autorun } = require("mobx");
class ObservableTodoStore {
todos = [];
constructor() {
makeObservable(this, {
todos: observable,
completedTodosCount: computed,
report: computed,
addTodo: action,
modifyTodo: action,
});
autorun(() => console.log(this.report));
}
get completedTodosCount() {
return this.todos.filter((todo) => todo.completed === true).length;
}
get report() {
if (this.todos.length === 0) return "";
const nextTodo = this.todos.find((todo) => todo.completed === false);
const percent = `进度:${this.completedTodosCount}/${this.todos.length}`;
return percent + `,准备:${nextTodo ? nextTodo.task : "<无>"}`;
}
modifyTodo(id, obj) {
this.todos[id] = {
...this.todos[id],
...obj,
};
}
addTodo(task) {
this.todos.push({
task: task,
completed: false,
assignee: "sunan",
});
}
}
const todoStore = new ObservableTodoStore();
todoStore.addTodo("阅读 MobX 教程");
todoStore.addTodo("试用 MobX");
todoStore.modifyTodo(0, { completed: true });
todoStore.modifyTodo(1, { task: "在自己的项目中试用 MobX" });
todoStore.modifyTodo(0, { task: "理解 MobX 教程" });
运行结果:
进度:0/1,准备:阅读 MobX 教程
进度:0/2,准备:阅读 MobX 教程
进度:1/2,准备:试用 MobX
进度:1/2,准备:在自己的项目中试用 MobX
普通版todolist(对照组)
下面的代码,在浏览器里面能用,在纯node
环境下,也能用。它就是一个普通的类,没有涉及到mobx
。
class TodoStore {
todos = [];
get completedTodosCount() {
return this.todos.filter((todo) => todo.completed === true).length;
}
get report() {
if (this.todos.length === 0) return "";
const nextTodo = this.todos.find((todo) => todo.completed === false);
const percent = `进度:${this.completedTodosCount}/${this.todos.length}`;
return percent + `,准备:${nextTodo ? nextTodo.task : "<无>"}`;
}
addTodo(task) {
this.todos.push({
task: task,
completed: false,
});
}
}
const todoStore = new TodoStore();
todoStore.addTodo("<0>阅读 MobX 教程"); // 添加新任务
console.log(todoStore.report); // 任务进度汇报
todoStore.addTodo("<1>试用 MobX");
console.log(todoStore.report);
todoStore.todos[0].completed = true; // 完成第一个进度(目前正式的`mobx`,并不推荐这么写)
console.log(todoStore.report); // 任务进度汇报
todoStore.todos[1].task = "<1>在自己的项目中试用 MobX"; // 修改未完成任务(第二个任务)的名称
console.log(todoStore.report);
todoStore.todos[0].task = "<0>理解 MobX 教程"; // 修改已完成任务(第一个任务)的名称,意义不大...
console.log(todoStore.report);
输出:
进度:0/1,准备:<0>阅读 MobX 教程
进度:0/2,准备:<0>阅读 MobX 教程
进度:1/2,准备:<1>试用 MobX
进度:1/2,准备:<1>在自己的项目中试用 MobX
进度:1/2,准备:<1>在自己的项目中试用 MobX
代码对比
两者最明显的区别是:普通代码的版本,需要【多次调用】.report
。而mbox
版本的,是通过autorun()
执行的,并没有明显的调用执行。
在任务调度一致的前提下,两者的输出是略有不同的。
mobx
版本下,输出为5条。顶部多一个"",尾部少一个输出。(所以,这里存在着怀疑)- 普通版本下,输出5条。
官方的说法是:“因为 report
实际上并没有因为第五行代码的重命名而发生改变,尽管它背后的数据变了。另一方面,更改第一个待办的名称确实更新了report
,因为report
正使用着那个新名字。这很好地证明了autorun
不仅监视观察着todos
数组,还监视着待办条目中的各个属性。”
代码编写方面,最显著的就是在类的构造器上,增加了下面的代码:
constructor() {
makeObservable(this, {
todos: observable, // 维护的状态
completedTodosCount: computed, // 属性值,带get开头的
report: computed,
addTodo: action, // 修改状态的函数
modifyTodo: action,
});
autorun(() => console.log(this.report)); // 自动执行,被观察的变量变化的话,它就会被执行
}
结语
本文以建立mbox
的初步印象为主要目的,mobx
的技术细节,后续再进行深入讨论。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。