canfoo/self-vue

有几个问题想问下

Wuou opened this issue · 1 comments

Wuou commented

1、 var dep = new Dep(); 这是消息订阅器放订阅者的集合容器,为什么要写在 defineReactive里面 这里递归后dep会被多次创建啊 难道dep不应该是只有一个消息订阅器吗?

2、 dep.notify(); 这里为什么要通知全部订阅者啊? 不应该是只通知与该数据字段变化所对应绑定的订阅者吗?
function defineReactive(data, key, val) {
observe(val); // 递归遍历所有子属性
var dep = new Dep();
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function() {
if (Dep.target) {. // 判断是否需要添加订阅者
dep.addSub(Dep.target); // 在这里添加一个订阅者
}
return val;
},
set: function(newVal) {
dep.notify(); // 如果数据变化,通知所有订阅者
}
});
}

@Wuou
dep消息订阅器确实是放订阅者的集合容器,但是是放相同类型(可以理解同一个key)的订阅者,而不是所有的订阅者,因为dep是连接observe 和 watcher的桥梁,所以它两的关系可以看作一个observe对应多个watcher,可以理解为一个observe就是一个dep实例,多个watcher就是存在这个dep实例里的subs列表内。
举个栗子
比如data = { a: 1, b: 2 }; 则这时候就会生成两个observe,假设为aobserve和bobserve,如果这时候模板是如下(例子1):

<div name="awatcher">{{a}}</div>
<div name="bwatcher">{{b}}</div>

则这个时候就两个watcher,即awatcher和bwatcher(这里假设命名方式以标签name来定),因为awatcher和bwatcher是不同类型的(data里的key分别为 a 和 b),所以就需要两个dep实例(假设分别为adep 和 bdep)来连接这两个observe(aobserve和bobserve),以此同时两个dep的subs都只有一个watcher,对应关系分别是awatcher和bwatcher,即 aobserve -- adep -- [awatcher];bobserve -- bdep -- [bwatcher]
这时候假设模板是这样的(例子2):

<div name="awatcher1">{{a}}</div>
<div name="awatcher2">{{a}}</div>
<div name="bwatcher">{{b}}</div>

如上,这个时候就有三个watcher,即awatcher1、awatcher2和bwatcher,因为awatcher1和awatcher2是同个类型的(data里的key都为 a),所以这个时候这时候awatcher1和awatcher2会归属到同一个dep实例里。同上面假设这时候它们的对应关系是这样的 aobserve -- adep -- [awatcher1,awatcher2],而bwatcher还是不变对应关系。

如果上面我解释的你明白的话,2个问题就都解决了。

  1. dep是会被多次创建,因为要对应不同的observe
  2. dep.notify();确实需要改变所有的watcher监听函数,如上例子2,如果这时候this.a 变化了,是不是应该更新所有自身的watcher,即awatcher1,awatcher2。