Intercept & Observe
Intercept & Observe
observe
和 intercept
可以用来监测单个 observable(它们不
追踪嵌套的 observable) 的变化。 intercept
可以在变化作用于 observable 之前监测和修改变化。 observe
允许你在 observable 变化之后拦截改变。
Intercept
用法: intercept(target, propertyName?, interceptor)
target
: 监测的 observable
intercept
应该告诉 MobX 对于当前变化需要做些什么。 因此,它应该做下列事情中的某个:
- 把从函数中接收到的
change
对象原样返回,这样变化会被应用。
该函数返回一个 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
该函数返回一个 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 永生
事件概览
intercept
和 observe
的回调函数接收一个事件对象,它至少有如下属性:
object
: 触发事件的 observable
对于每种类型可用的附加字段:
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)
明确地订阅特定属性来观察它们。