前文中我们在修改 data 属性后,手动调用了 _update 更新视图,这是不方便的,所以需要实现监听 data 的变化,自动触发页面的更新:
<div id="app" style="color:red;background:yellow">
{{name}} {{age}} {{name}} {{name}} {{name}}
</div>
所以我们想到给模板中的属性(e.g. {{name}} 、 {{age}} …),都添加一个对应的收集器(dep)
然后页面渲染的时候,将渲染逻辑封装到 watcher 中(vm._update(vm._render()))
让 dep 记住这些 watcher 即可, 等到属性变化了可以找到对应的 dep 中存放的 watcher 进行重新渲染
如下图所示,每个组件都会有自己的 watcher ,当只有 num 变化,而 name 和 age 没有变化时,其实只用更新 侧边栏 一个组件,所以为了做区分,需要给每个 watcher 分配一个唯一 id。
这也侧面说明了 Vue 组件化除了 复用、 方便维护 外的另一个好处:局部渲染更新

dep 和 watcher 的关系是 多对多关系:

src/observe/watch.js
Watcher 接收三个参数:
vm
watcher 属于哪个实例fn
vm 对应的渲染函数options
watcher 是不是一个渲染 watcherlet id = 0;
class Watcher { // 不同组件有不同的 watcher 目前只有一个 渲染根实例的
constructor(vm, fn, options) {
this.id = id++;
this.renderWatcher = options; // options = true 表明 watcher 是一个渲染 watcher
this.getter = fn; // getter 意味着调用这个函数可以发生取值操作
this.get(); // 默认先去取值一次
}
get() {
this.getter(); // 会去 vm 上取值 vm._update(vm._render) 取name 和age
}
}
// 需要给每个属性增加一个dep, 目的就是收集watcher
// 一个组件(视图)中 有多个属性 (n个属性会对应一个组件(视图)) n个dep对应一个watcher
// 1个属性 对应着多个组件(视图) 1个dep对应多个watcher
// 多对多的关系
export default Watcher;
在 lifecycle.js 中调用 watcher 更新视图