非常教程

MobX参考手册

工具函数

Intercept & Observe

observeintercept 可以用来监测单个 observable(它们追踪嵌套的 observable) 的变化。 intercept 可以在变化作用于 observable 之前监测和修改变化。 observe 允许你在 observable 变化之后拦截改变。

Intercept

用法: intercept(target, propertyName?, interceptor)

  • target: 监测的 observable
  • propertyName: 可选参数,用来指定某个属性进行拦截。注意,intercept(user.name, interceptor)intercept(user, "name", interceptor) 根本是完全不同的。前者尝试给 user.name(或许根本不是一个 observable) 里面的当前值添加一个拦截器,而后者拦截 username 属性的变化。
  • interceptor: 在每次变化作用于 observable 后调用的回调函数。接收一个用来描述变化的对象。

intercept 应该告诉 MobX 对于当前变化需要做些什么。 因此,它应该做下列事情中的某个:

  1. 把从函数中接收到的 change 对象原样返回,这样变化会被应用。
  2. 修改 change 对象并将其返回,例如数据标准化。但不是所有字段都是可以修改的,参见下面。
  3. 返回 null,这表示此次变化可以被忽略而且不会应用。这是一个强大的概念,例如可以使你的对象临时性的不可改变。
  4. 抛出异常,例如如果一些不变量未被满足。

该函数返回一个 disposer 函数,当调用时可以取消拦截器。 可以为同一个 observable 注册多个拦截器。 它们会按照注册的顺序串联起来。 如果一个拦截器返回 null 或抛出异常,其它的拦截器不会再执行。 还可以注册一个拦截器同时作用于父对象和某个属性。 在这种情况下,父对象的拦截器在属性拦截器之前运行。

const theme = observable({
  backgroundColor: "#ffffff"
})

const disposer = intercept(theme, "backgroundColor", change => {
  if (!change.newValue) {
    // 忽略取消设置背景颜色
    return null;
  }
  if (change.newValue.length === 6) {
    // 补全缺少的 '#' 前缀
    change.newValue = '#' + change.newValue;
    return change;
  }
  if (change.newValue.length === 7) {
      // 这一定是格式正确的颜色代码!
      return change;
  }
  if (change.newValue.length > 10) disposer(); // 不再拦截今后的任何变化
  throw new Error("This doesn't like a color at all: " + change.newValue);
})
Copy

Observe

用法: observe(target, propertyName?, listener, invokeImmediately?)

  • target: 观察的 observable
  • propertyName: 可选参数,用来指定某个属性进行观察。注意,observe(user.name, listener)observe(user, "name", listener) 根本是完全不同的。前者观察 user.name(或许根本不是一个 observable) 里面的当前值,而后者观察 username属性。
  • listener: 在每次变化作用于 observable 后调用的回调函数。接收一个用来描述变化的对象,除了装箱的 observable,它调用 listener 有两个参数: newValue、oldValue
  • invokeImmediately: 默认是 false。如果你想 observe 直接使用 observable 的状态(而不是等待第一次变化)调用 listener 的话,把它设置为 true。不是所有类型的 observable 都支持。

该函数返回一个 disposer 函数,当调用时可以取消观察者。 注意,transaction 不影响 observe 方法工作。 意味着即使在一个 transaction 中,observe 也会触发每个变化的监听器。 因此,autorun 通常是一个更强大的和更具声明性的 observe 替代品。

observe 会响应对应的变动,而像是 autorun reaction 则会对新值做出响应。大多数情况下,后者足够用了。

示例:

import {observable, observe} from 'mobx';

const person = observable({
    firstName: "Maarten",
    lastName: "Luther"
});

const disposer = observe(person, (change) => {
    console.log(change.type, change.name, "from", change.oldValue, "to", change.object[change.name]);
});

person.firstName =  "Martin";
// 输出: 'update firstName from Maarten to Martin'

disposer();
// 忽略任何未来的变化

// 观察单个字段
const disposer2 = observe(person, "lastName", (change) => {
    console.log("LastName changed to ", change.newValue);
});
Copy

相关博客: Object.observe 已死。mobx.observe 永生

事件概览

interceptobserve 的回调函数接收一个事件对象,它至少有如下属性:

  • object: 触发事件的 observable
  • type: 当前事件类型(字符串)

对于每种类型可用的附加字段:

observable 类型

事件类型

属性

描述

intercept 期间能否获得

能否被 intercept 修改

对象

add

name

添加的属性名称

newValue

分配的新值

update*

name

更新的属性名称

newValue

分配的新值

oldValue

被替换的值

数组

splice

index

splice 的起始索引。 push、 unshift、 replace 等方法可以触发 splice。

removedCount

删除项的数量

added

添加到数组中的项

removed

数组中移除的项

addedCount

添加项的数量

update

index

更新的单个项的索引

newValue

(将)分配的新值

oldValue

被替换的值

映射

add

name

添加项的名称

newValue

分配的新值

update

name

更新项的名称

newValue

分配的新值

oldValue

被替换的值

delete

name

删除项的名称

oldValue

删除项的值

Boxed & computed observables

create

newValue

创建期间分配的新值。只有 boxed observables 的 spy 事件可获得

update

newValue

分配的新值

oldValue

observable 的前一个值

* 注意,对象的 update 事件不会为更新的计算值(因为它们没有变化)触发。但是可以通过使用 observe(object, 'computedPropertyName', listener) 明确地订阅特定属性来观察它们。

MobX

MobX 是一个经过战火洗礼的库,它通过透明的函数响应式编程(transparently applying functional reactive programming - TFRP)使得状态管理变得简单和可扩展。

MobX目录

1.简介 | Introduction
2.API 概览
3.观察 | Observable
4.对 Observables 作出响应
5.改变 Observables
6.工具函数
7.贴士与技巧