Dep

# Dep

// 观察者
class Dep {
  constructor() {
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }

  depend() {
    if (Dep.target) {
      Dep.target.addDep(this);
    }
  }

  notify() {
    this.subs.forEach((sub) => sub.update());
  }
}

# Watcher

// 被观察者
class Watcher {
  constructor(vm, expOrFn) {
    this.vm = vm;
    this.getter = expOrFn;
    this.value;
  }

  get() {
    Dep.target = this;

    var vm = this.vm;
    var value = this.getter.call(vm, vm);
    return value;
  }

  evaluate() {
    this.value = this.get();
  }

  addDep(dep) {
    dep.addSub(this);
  }

  update() {
    console.log("更新, value:", this.value);
  }
}

# 实例

// 观察者实例
var dep = new Dep();

//  被观察者实例
var watcher = new Watcher({ x: 1 }, (val) => val);
watcher.evaluate();

// 观察者监听被观察对象
dep.depend();

dep.notify();
  1. 通过 watcher.evaluate() 将自身实例赋值给 Dep.target;
  2. 调用 dep.depend() 将 dep 实例将 watcher 实例 push 到 dep.subs 中;
  3. 通过数据劫持,在调用被劫持的对象的 set 方法时,调用 dep.subs 中所有的 watcher.update();
  • defineProperty
Object.defineProperty(obj, key, {
  enumerable: true,
  configurable: true,
  get: function reactiveGetter() {
    const value = getter ? getter.call(obj) : val;
    if (Dep.target) {
      dep.depend();
      if (childOb) {
        childOb.dep.depend();
      }
      if (Array.isArray(value)) {
        dependArray(value);
      }
    }
    return value;
  },
  set: function reactiveSetter(newVal) {
    const value = getter ? getter.call(obj) : val;
    if (newVal === value || (newVal !== newVal && value !== value)) {
      return;
    }
    if (setter) {
      setter.call(obj, newVal);
    } else {
      val = newVal;
    }
    childOb = !shallow && observe(newVal);
    dep.notify();
  },
});
  • Proxy
Proxy(data, {
  get(target, key) {
    return target[key];
  },
  set(target, key, value) {
    let val = Reflect.set(target, key, value);
    _that.$dep[key].forEach((item) => item.update());
    return val;
  },
});