mobx 学习:Mobx思想
The gist of MobX · MobX
三个概念
- State(状态)
- Actions(动作)
- Derivations(派生)
原则
Mobx 使用单向数据流,利用 action
改变 state
,进而更新所有受影响的 view
- 所有的
derivations
将在state
改变时自动且原子化地更新。因此不可能观察中间值。 - 所有的
dervations
默认将会同步更新,这意味着action
可以在state
改变 之后安全的直接获得computed
值。 computed value
的更新是惰性的,任何computed value
在需要他们的副作用发生之前都是不激活的。- 所有的
computed value
都应是纯函数,他们不应该修改state
。
State: 定义 State 并使其可观察
makeAutoObservable 可以简化操作,这个例子中为了演示
import { makeObservable, observable, action } from 'mobx';
class Todo {
id = Math.random();
title = '';
finished = false;
constructor(title) {
makeObservable(this, {
title: observable,
finished: observable,
toggle: action,
});
this.title = title;
}
toggle() {
this.finished = !this.finished;
}
}
使用 Action 更新 State
Action(动作) 是任意可以改变 State(状态) 的代码,比如用户事件处理、后端推送数据处理、调度器事件处理等等。
使用 Action 可以帮助您更好地组织代码,并防止您在无意中修改 State。
在 MobX 术语中,可以修改 State 的方法被称为 action(动作) 。这与基于当前状态来生成新信息的 view(视图) 是不同的。 您代码中的每一个方法只应完成上述两个目标中的一个。
Derivations: Mobx 区分了两种 Derivation
Computed values,总是可以通过纯函数从当前的可观测 State 中派生。
Reactions, 当 State 改变时需要自动运行的副作用 (命令式编程和响应式编程之间的桥梁)
使用 Reaction 的原则
- 当最开始使用MobX时,人们容易过度使用 Reaction。
- 黄金法则是,如果要基于当前 State 创建值,请始终使用 computed。
通过 computed 对派生值进行建模
import { makeObservable, observable, computed } from 'mobx';
class TodoList {
todos = [];
get unfinishedTodoCount() {
return this.todos.filter((todo) => !todo.finished).length;
}
constructor(todos) {
makeObservable(this, {
todos: observable,
unfinishedTodoCount: computed,
});
this.todos = todos;
}
}
常用的 Reaction
- computed
- observer
- 特殊业务场景:可以使用 autorun ,reaction 或 when 方法来订制你的特殊业务场景
// 一个自动观察state的函数
autorun(() => {
console.log("Tasks left: " + todos.unfinishedTodoCount)
})
Q&A
使用mobx时修改state可以不用action,为什么教程里强调要使用?(高赞回复其实是错的)
尽管如此,MobX 还是提供了 actions 这个可选的内置概念。 如果你现在就想要了解如何编写 actions,请阅读 Actions 章节。很简单! 使用 actions 是有优势的: 它们可以帮助你把代码组织的更好,还能在状态何时何地应该被修改这个问题上帮助你做出明智的决定。这是官网的说法,说是可选的,我的意思是我的state里有很多个像loadingState = fasle,isAnimationShow = false,selectElementIndex = 0, selectGroupIndex = 0 像这样的属性,如果要修改的话,不是得每一个都要写一个action?
其它回复:里面内置的transaction可以避免多个observable的修改导致不必要的多次渲染
必须要通过
action
去更新Store?
原理上不必要,原则上必要。你直接mutable的方式直接更改Store也是能够触发响应式更新,但是mobx强烈不建议你这样做,因为你会丢失以下好处:
(1) 能够清晰表达出一个函数修改状态的意图,有利于项目维护
(2) action结合开发者工具,提供了非常有用的调试信息
当启用严格模式时,修改store状态需要强制使用action,参见全局配置enforceActions
。MobX并不像redux
那样,从原理上就限制了state
的更新方式(防止玩花活儿,如: _.set(obj,'xx.x.y.x.z', ‘yourvalue’)
,只能靠这种约定的方式去限制。所以强烈建议开启此选项。
关于这个问题,个人测试结果
- 能够清晰表达出一个函数修改状态的意图,有利于项目维护
action
结合开发者工具,提供了非常有用的调试信息- 当启用严格模式时,修改
store
状态需要强制使用action
,参见全局配置enforceActions
- 里面内置的
transaction
可以避免多个observable
的修改导致不必要的多次渲染 这个测试过了简单多种状态还是可以自动判断,只执行一次的,所以观点不完全对