返回

**Vue源码解读—手摸手教你实现一个简单Vue(3):dep和watcher的编写**

前端

前言

在上一篇文章中,我们实现了Observer,这一篇文章我们就来讲讲Dep和Watcher的实现。依然如前,在文章末尾我编写了一个js的简单测试版供你边测试边读懂这一节的文字。

一、Dep的实现

Dep是一个类,它的作用是收集Watcher,当数据发生变化时,通知Watcher更新。

class Dep {
  constructor() {
    this.subscribers = [];
  }

  addSubscriber(watcher) {
    this.subscribers.push(watcher);
  }

  notify() {
    this.subscribers.forEach(watcher => {
      watcher.update();
    });
  }
}

二、Watcher的实现

Watcher是一个类,它的作用是当数据发生变化时,更新视图。

class Watcher {
  constructor(vm, expr, cb) {
    this.vm = vm;
    this.expr = expr;
    this.cb = cb;

    // 在实例化的时候,立刻计算expr的值,并将其作为初始值
    this.value = this.get();
  }

  get() {
    // 将当前的Watcher实例添加到Dep中,以便在数据发生变化时通知它
    Dep.target = this;
    const value = compileUtil.getValue(this.vm, this.expr);
    Dep.target = null;

    return value;
  }

  update() {
    const value = this.get();

    // 对比新的值和旧的值是否发生了变化,如果变化了,则调用cb
    if (value !== this.value) {
      this.cb(value, this.value);
      this.value = value;
    }
  }
}

三、测试

我们可以在浏览器中创建一个简单的Vue实例来测试Dep和Watcher的实现。

const vm = new Vue({
  data: {
    a: 1
  }
});

vm.$watch('a', (newValue, oldValue) => {
  console.log(`a的值从${oldValue}变为${newValue}`);
});

vm.a = 2;

运行这段代码,你将在控制台看到如下输出:

a的值从1变为2

这表明我们的Dep和Watcher已经正确地实现了。

总结

在这一篇文章中,我们实现了Dep和Watcher,并通过一个简单的测试实例验证了它们的正确性。希望这篇文章能帮助你更好地理解Vue3的响应式原理。