watchEffect

大约 1 分钟

前言

在vue3的整个响应式系统中,靠的是 watchEffect函数 收集依赖,数据发生变化时触发依赖。

watchEffect

收集依赖,触发依赖

思路

定义一个临时变量;

将传入的依赖记录到临时变量中;
执行依赖;
清空临时变量;

实现

// 记录要收集的依赖的变量
let activeEffect;

/**
 * @description: 收集触发依赖
 * @param {function} effect 依赖
 */
function watchEffect(effect) {
  activeEffect = effect;
  effect();
  activeEffect = null;
}

dep

现在收集触发依赖的方法有了,就需要在访问数据时记录依赖,修改数据时触发依赖,即 gettersetter

每一个数据都可以是一个实例,该实例记录着与自己有关的所有依赖

class Dep {
  constructor(value) {
    // 存储所有关于该数据的依赖
    this.subscribers = new Set();
    // 数据
    this._value = value;
  }
  // getter
  get value() {
    // 访问数据时记录依赖
    depend();
    return this._value;
  }
  // setter
  set value(newValue) {
    this._value = newValue;
    // 修改数据时触发依赖
    notify();
  }
  depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect);
    }
  }
  notify() {
    this.subscribers.forEach((effect) => {
      effect();
    });
  }
}

结合

const dep = new Dep("hello");
watchEffect(() => {
  // 访问了数据,所以该依赖被记录了
  console.log(dep.value);
});

// 修改数据,依赖被触发
dep.value = "world"; // world

总结

本节为了理清收集触发依赖的流程,所以使用了 dep 这个类来实现逻辑,但 getter 和 setter 无法捕获引用类型数据的操作,所以下节将实现 reactive函数 来实现对引用类型数据的操作捕获。