# 创建可观测状态
一共有三种方式创建可观测状态。
1.makeObservable。捕获监听对象并手动映射注解。
2.makeAutoObservable。加强版的 makeObservable ,会自动映射注解(减低心智,推荐使用)。
3.observable。以函数调用的方式进行注解,将整个对象变为可观测状态。
# makeObservable
makeObservable(target, annotations?, options?)
import { makeObservable, observable, computed, action, flow } from "mobx"
class Doubler {
value
constructor(value) {
makeObservable(this, {
value: observable,
double: computed,
increment: action,
fetch: flow
})
this.value = value
}
get double() {
return this.value * 2
}
increment() {
this.value++
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# makeAutoObservable
makeAutoObservable(target, overrides?, options?)
自动推断规则:
- 所有 自有 属性都成为
observable
。 - 所有
get
ters 都成为computed
。 - 所有
set
ters 都成为action
。 - 所有 prototype 中的 functions 都成为
autoAction
。 - 所有 prototype 中的 generator functions 都成为
flow
。(需要注意,generators 函数在某些编译器配置中无法被检测到,如果 flow 没有正常运行,请务必明确地指定flow
注解。) - 在
overrides
参数中标记为false
的成员将不会被添加注解。例如,将其用于像标识符这样的只读字段。
# observable
observable(source, overrides?, options?)
使用 proxy 包装对象,并将其变为可观测的。
特性:
- 之后被添加到这个对象中的属性也将被侦测并使其转化为可观察对象(除非禁用 proxy (opens new window))
observable
方法也可以被像 arrays (opens new window),Maps (opens new window) 和 Sets (opens new window) 这样的集合调用。这些集合也将被克隆并转化为可观察对象。
# 可用的注解 (opens new window)
注解 | 描述 |
---|---|
observable observable.deep | 定义一个存储 state 的可跟踪字段。如果可能,任何被赋值给 observable 的字段都会基于它自己的类型被(深度)转化为observable 、autoAction 或 flow 。只有 plain object 、array 、Map 、Set 、function 、generator function 可以转换,类实例和其他实例不会被影响。 |
observable.ref | 类似于 observable ,但只有重新赋值才会被追踪。所赋的值会被完全忽略,并且将不会主动转化为 observable /autoAction /flow 。比方说,在你打算将不可变数据存储在可观察字段中时,可以使用这个注解。 |
observable.shallow | 类似于 observable.ref 但是是用于集合的。任何所赋的集合都会被转化为可观察值,但是其内部的值并不会变为可观察值。 |
observable.struct | 类似于 observable ,但是会忽略所赋的值中所有在结构上与当前值相同的值。 |
action | 把一个函数标记为会修改 state 的 action。查看 actions (opens new window) 获取更多信息。不可写。 |
action.bound | 类似于 action,但是会将 action 绑定到实例,因此将始终设置 this 。不可写。 |
computed | 可以用在 getter (opens new window) 上,用来将其声明为可缓存的派生值。查看 computeds (opens new window) 获取更多信息。 |
computed.struct | 类似于 computed ,但如果重新计算后的结果在结构上与之前的结果相等,那么观察者将不会收到通知。 |
true | 推断最佳注解。查看 makeAutoObservable (opens new window) 获取更多信息。 |
false | 刻意不为该属性指定注解。 |
flow | 创建一个 flow 管理异步进程。查看 flow (opens new window) 获取更多信息。需要注意的是,推断出来的 TypeScript 返回类型可能会出错。 不可写。 |
flow.bound | 类似于 flow, 但是会将 flow 绑定到实例,因此将始终设置 this 。 不可写。 |
override | 用于子类覆盖继承的 action ,flow ,computed ,action.bound (opens new window)。 |
autoAction | 不应被显式调用,但 makeAutoObservable 内部会对其进行调用,以便根据调用上下文将方法标识为 action 或者派生值。 |
# 局限性 (opens new window)
详细见文档链接。
# Options (opens new window)
上面的 API 都有一个可选的 options
参数,该参数是一个对象,支持以下选项:
autoBind: true
默认使用action.bound
/flow.bound
,而不使用action
/flow
。不影响被显式注释过的成员。deep: false
默认使用observable.ref
,而不使用observable
。不影响被显式注释过的成员。name: <string>
为对象提供一个调试名称,该名称将被打印在错误消息和 reflection API 中。proxy: false
迫使observable(thing)
使用非 proxy (opens new window) 的实现。如果对象的结构不会随着时间变化,那么这就是一个很好的选择,因为非代理对象更容易调试并且速度更快。请参见 避免代理 (opens new window)。
# 将 observable 转换回普通的 JavaScript 集合
有时有必要将可观察的数据结构转换回原生的数据结构。 例如,将可观察对象传入一个无法跟踪可观察对象的 React 组件时,或者想要获取一个不会再被更改的副本时。
要进行浅转换,用常用的 JavaScript 操作就可以做到:
const plainObject = { ...observableObject }
const plainArray = observableArray.slice()
const plainMap = new Map(observableMap)
1
2
3
2
3
要将数据树递归地转换为普通对象,可使用 toJS
(opens new window) 工具函数。 对于类,建议实现一个 toJSON()
方法,因为这样会被 JSON.stringify
识别出来。