前文中我们在修改 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 进行重新渲染

Dep 收集者和 Watcher 观察者

如下图所示,每个组件都会有自己的 watcher ,当只有 num 变化,而 nameage 没有变化时,其实只用更新 侧边栏 一个组件,所以为了做区分,需要给每个 watcher 分配一个唯一 id

这也侧面说明了 Vue 组件化除了 复用方便维护 外的另一个好处:局部渲染更新

image.png

Dep 和 Watcher 之间是 多对多关系

depwatcher 的关系是 多对多关系:

image.png

src/observe/watch.js

Watcher 接收 render 函数渲染视图

Watcher 接收三个参数:

let 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 更新视图