MobX会对在任何一个被监控的function执行的过程中被读取的已经存在的observable的属性进行反应。
上面的这句话里面有几个关键的点:
1:正在被读取
正在读取的意思是:取用一个对象的属性。例如:user.name或者user['name']
2:可被监控的function
可被监控的function是computed的一个表述,有以下几种情况:
1:一个observer的组件的render()方法
2:作为第一个参数传给when(), reaction()和autorun()的function
3:在...过程中
在...过程中,意思是只有在方法的执行中被读取的observable才被track了。这些observable是被直接的还是间接地被使用,并不影响。
换句话说,MboX不会对以下情况进行反应:
1:从一个observable读取的值,但是没有被用在一个可被监控的function里面
2:在一个异步调用的代码块里被读取的变量
一:MobX监控属性的读取,而不是属性的值
我们以下面的一段代码示例来解释上面的这条规则是设么意思:
let message = observable({
title: "Foo",
author: {
name: "Michel"
},
likes: ["John", "Sara"]
})
在内存里面它看起来如下图所示。绿色的模块表示是observable的属性。注意,这些数值本身不是observable的!
现在基本上,MobX做的事情就是记录在你的function里面,你使用的是哪个箭头。在那之后,不论哪个箭头发生变化,他都会重新运行。也就是当这些箭头指向一个其他的值。
Examples
我们基于上面的message这个observable。
正确:在一个被监控的方法里面读取一个属性:
autorun(()=>{
console.log(message.title)
})
message.title = 'Bar'
以上代码会如我们期待的那样。因为.title是在autorun里面被读取,且之后改变了,所以这个改变会被识别到。
不正确:修改一个不是observable的reference
autorun(() => {
console.log(message.title)
})
message = observable({ title: "Bar" })
上面的代码不会反应。因为虽然message改变了,但是message不是一个observable,而仅仅是一个指向一个observable的变量,而这个变量(这个reference)它自己不是一个observable。
不正确:在一个监控方法外读取属性
var title = message.title
autorun(() => {
console.log(title)
})
message.title = "Bar"
这段代码也不会反应,因为message.title是在监控方法外被读取,因而它只是包含message.title的值(也就是'Foo')。所以,title不是一个observable,所以autorun不会反应。
正确: 在一个监控方法内部读取属性
autorun(() => {
console.log(message.author.name)
})
message.author.name = "Sara"
message.author = { name: "John" }
以上代码的最后2行代码都会导致MboX反应。因为.author和.author.name都在一个autorun里面被引用,这就允许MboX去跟踪这些references。
不正确:给一个observable存储了一个没有被跟踪的本地变量
const author = message.author
autorun(() => {
console.log(author.name)
})
message.author.name = "Sara"
message.author = { name: "John" }
上面的代码,倒数第一行不会触发MobX反应,而倒数第二行会。因为,在autorun里面只获取了author.name,而message.author没有在autorun里面被使用,所以message.author的变化没有被跟踪,在autorun里面使用的还是老的author。
接下来我们要看Array了。Array的情况与Object有一些区别。
以下的例子,依然基于以下的代码:
let message = observable({
title: "Foo",
author: {
name: "Michel"
},
likes: ["John", "Sara"]
})
正确:在一个被监控的方法里读取Array的属性
autorun(() => {
console.log(message.likes.length)
})
message.likes.push("Jennifer")
以上的代码会按照我们期待的那样执行。.length是Array的一个属性。注意:上面的代码会对array的任何改变都作出反应。Array是检测它的全部,而不是像map或者对象那样监控每一个键值对。例如:
autorun(() => {
console.log(message.likes[0])
})
message.likes.push("Jennifer")
以上的这段代码,新增加了一个元素,使得Array本身改变了,所以会导致autorun里面的代码会被重新执行一遍。Array的下标被当做属性被访问,但是只有当下标没有越界的情况下才有效。Mobx不会监控还不存在的下标或者对象的属性(除非是用map)。
不正确:在被监控的方法里访问越界的元素
autorun(() => {
console.log(message.likes.join(", "))
})
message.likes[2] = "Jennifer"
以上的代码不会成功。因为访问了越界的下标。
正确: 在监控方法里面访问Array的方法
autorun(() => {
console.log(message.likes.join(", "))
})
message.likes.push("Jennifer")
以上代码会按照期望的触发autorun的执行。Array所有的没有修改原Array的方法,都会被自动监控。
不正确:使用了observable,但是没有读取它的任何属性
autorun(() => {
message.likes
})
message.likes.push("Jennifer")
以上的代码不会使得autorun在执行。因为,likes数组自己本身没有被autorun使用,而是likes数组的reference被autorun使用了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。