• observable 调节器
    • 深层可观察性
    • 引用可观察性
    • 浅层可观察性
    • Action & Computed
    • asStructure
    • 调节器的效果

    observable 调节器

    调节器可以作为装饰器或者组合 extendObservableobservable.object 使用,以改变特定属性的自动转换规则。

    • observable.deep: 任何 observable 都使用的默认的调节器。它把任何分配的、非原始数据类型的、非 observable 的值转换成 observable。
    • observable.ref: 禁用自动的 observable 转换,只是创建一个 observable 引用。
    • observable.shallow: 只能与集合组合使用。 将任何分配的集合转换为浅 observable (而不是深 observable)的集合。 换一种说法; 集合中的值将不会自动变为 observable。
    • computed: 创建一个衍生属性, 参见 computed
    • action: 创建一个动作, 参见 action

    深层可观察性

    当 MobX 创建一个 observable 对象时,(使用 observableobservable.objectextendObservable),它引入的 observable 属性默认是使用 deep 调节器的。deep 调节器主要是为任何新分配的值递归调用 observable(newValue)
    会依次使用 deep 调节器…你可以想象。

    这是一个非常便利的默认设置。无需额外的工作,分配给 observable 的所有值本身也将转变成 observable(除非它们已经是),因此不需要额外的工作就可使对象转变成深 observable 。

    引用可观察性

    然后在某些情况下,不需要将对象转变成 observable 。
    典型案例就是不可变对象,或者不是由你管理,而是由外部库管理的对象。
    例如 JSX 元素、DOM 元素、像 History、window 这样的原生对象,等等。
    对于这类对象,只需要存储引用而不用把它们转变成 observable 。

    对于这些情况,可以使用 ref 调节器。它会确保创建 observable 属性时,只追踪引用而不会把它的值转变成 observable 。
    示例:

    1. class Message {
    2. @observable message = "Hello world"
    3. // 虚构的例子,如果 author 是不可变的,我们只需要存储一个引用,不应该把它变成一个可变的 observable 对象
    4. @observable.ref author = null
    5. }

    或者使用 ES5 语法:

    1. function Message() {
    2. extendObservable({
    3. message: "Hello world",
    4. author: observable.ref(null)
    5. })
    6. }

    注意,可以通过使用 const box = observable.shallowBox(value) 来创建一个装箱的 observable 引用

    浅层可观察性

    observable.shallow 调节器会应用“单层”可观察性。如果想创建一个 observable 引用的集合,那你会需要它。
    如果新集合分配给具有此调节器的属性,那么它会转变成 observable,但它的值将保持原样,不同于 deep 的是它不会递归。
    示例:

    1. class AuthorStore {
    2. @observable.shallow authors = []
    3. }

    在上面的示例中,使用普通的 author 数组分配给 authors 的话,会使用 observables 数组来更新 author,observables 数组包含原始的、非 observable 的 author 。

    注意这些方法可用于手动创建浅集合: observable.shallowObjectobservable.shallowArrayobservable.shallowMapextendShallowObservable

    Action & Computed

    actionaction.boundcomputedcomputed.struct 同样可以作为调节器使用。
    参见 computedaction

    1. const taskStore = observable({
    2. tasks: observable.shallow([]),
    3. taskCount: computed(function() {
    4. return this.tasks.length
    5. }),
    6. clearTasks: action.bound(function() {
    7. this.tasks.clear()
    8. })
    9. })

    asStructure

    MobX 2 中有 asStructure 调节器,它在实践中极少被使用,或者只能在使用 reference / shallow 更适合(例如使用不可变数据)的情况下使用。
    计算属性和 reaction 的结构比较仍是可能的。

    调节器的效果

    1. class Store {
    2. @observable/*.deep*/ collection1 = []
    3. @observable.ref collection2 = []
    4. @observable.shallow collection3 = []
    5. }
    6. const todos = [{ test: "value" }]
    7. const store = new Store()
    8. store.collection1 = todos;
    9. store.collection2 = todos;
    10. store.collection3 = todos;

    完成这些分配后:

    1. collection1 === todos 是 false; todos 的内容会被克隆至一个新的 observable 数组。
    2. collection1[0] === todos[0] 是 false; 第一个 todo 是个普通对象,因此它被克隆至一个存储在数组中的 observable 对象。
    3. collection2 === todos 是 true; todos 保持不变, 而且是非 observable。 只有 collection2 属性本身是 observable 。
    4. collection2[0] === todos[0] 是 true; 理由同 3。
    5. collection3 === todos 是 false; collection3 是一个新的 observable 数组。
    6. collection3[0] === todos[0] 是 true; collection3 的值只是浅的转变成 observable,但数组的内容保持不变。