# Mobx
一个基于 react 的一个响应式更新状态库,比较好用的一点是,其定义的数据可以类似 state 被 UI 所追踪,用 vue 的类似实现来写 react,视图与逻辑分离,还是挺爽的。
# 示例
import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react"
// 对应用状态进行建模。
class Timer {
secondsPassed = 0
constructor() {
makeAutoObservable(this)
}
increase() {
this.secondsPassed += 1
}
reset() {
this.secondsPassed = 0
}
}
const myTimer = new Timer()
// 构建一个使用 observable 状态的“用户界面”。
const TimerView = observer(({ timer }) => (
<button onClick={() => timer.reset()}>已过秒数:{timer.secondsPassed}</button>
))
ReactDOM.render(<TimerView timer={myTimer} />, document.body)
// 每秒更新一次‘已过秒数:X’中的文本。
setInterval(() => {
myTimer.increase()
}, 1000)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 基本概念
- State(状态)
- Actions(动作)
- Derivations(派生)
# State
数据状态。
如何将数据标识为 mobx 的state?
通过 makeObservable 并将属性标识为 observable:
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
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Actions
更改数据状态。
可以理解为数据提交,主要是为了防止直接修改数据,使得数据的更改变得难以追踪和维护。
如上面示例中的 toggle 就是一个 action,它通知 finished 变更为 !finished。
# Derivations
派生:任何基于 state 进行处理的东西。
# 主要分为两大类:
1.Computed :计算属性,基于 state 二次加工的数据。
2.Reactions:变化,当 State 改变时需要自动运行的副作用。
示例:
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
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这里将 unfinishedTodoCount 标识为 computed,每当其依赖的状态(即todos)变更时,它也会跟着变更,底层原理:proxy。
Reaction 其实原理与其类似,只不过为了分类将其概念抽离了出来,其不返回数据,只产生副作用,一般用来做什么?如打印到控制台、发出网络请求、增量更新 React 组件树以便更新 DOM 等。
到目前为止,最常用的 reaction 形式是UI组件。
# 如何自定义 reaction :
通常情况下你不需要使用它们,可以使用 autorun
(opens new window) ,reaction
(opens new window) 或 when
(opens new window) 方法来订制你的特殊业务场景。
比如,下面的 autorun
将在unfinishedTodoCount
的数量发生变化时输出日志。
// 一个自动观察state的函数
autorun(() => {
console.log("Tasks left: " + todos.unfinishedTodoCount)
})
2
3
4
# 响应式 React 组件
使用 observer 将 react 组件与 state 相关联。
import * as React from "react"
import { render } from "react-dom"
import { observer } from "mobx-react-lite"
const TodoListView = observer(({ todoList }) => (
<div>
<ul>
{todoList.todos.map(todo => (
<TodoView todo={todo} key={todo.id} />
))}
</ul>
Tasks left: {todoList.unfinishedTodoCount}
</div>
))
const TodoView = observer(({ todo }) => (
<li>
<input type="checkbox" checked={todo.finished} onClick={() => todo.toggle()} />
{todo.title}
</li>
))
const store = new TodoList([new Todo("Get Coffee"), new Todo("Write simpler code")])
render(<TodoListView todoList={store} />, document.getElementById("root"))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24