vue3基礎知識學習系列(二)響應式原理實現

使用對象的 set/get 方法 模擬實現 vue3 ref 單數據響應

const targetMap = new Map();
let currentEffect;
class Dep {
  constructor(val) {
    this.effects = new Set();
    this._val = val;
  }
  get value() {
    this.depend();
    return this._val;
  }
  set value(newVal) {
    this._val = newVal;
    this.notice();
  }
  // 收集依賴
  depend() {
    if (currentEffect) {
      this.effects.add(currentEffect);
    }
  }
  // 觸發依賴
  notice() {
    this.effects.forEach((effect) => {
      effect();
    });
  }
}
function effectWatch(effect) {
  // 依賴收集
  currentEffect = effect;
  effect();
  currentEffect = null;
}

const dep = new Dep(10);
let b;
effectWatch(() => {
  b = dep.value + 10;
  console.log(b); // 初始值打印爲 10  dep.value修改後打印爲 20
});
// 值變更 通知 觸發依賴 更新變量
dep.value = 20;

使用 Proxy/Reflect 實現 vue3 reactive 函數的實現原理

const targetMap = new Map(); //存儲指定key的對象
let currentEffect;
class Dep {
  constructor(val) {
    this.effects = new Set();
    this._val = val;
  }
  // 收集依賴
  depend() {
    if (currentEffect) {
      this.effects.add(currentEffect);
    }
  }
  // 觸發依賴
  notice() {
    this.effects.forEach((effect) => {
      effect();
    });
  }
}
function effectWatch(effect) {
  // 依賴收集
  currentEffect = effect;
  effect();
  currentEffect = null;
}

function getDep(target, key) {
  // key - dep依賴收集
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }
  let dep = depsMap.get(key);
  if (!dep) {
    dep = new Dep();
    depsMap.set(key, dep);
  }
  return dep;
}
function reactive(raw) {
  //代理對象所有屬性
  return new Proxy(raw, {
    get(target, key) {
      const dep = getDep(target, key);
      // 依賴收集
      dep.depend();
      return Reflect.get(target, key);
    },
    set(target, key, value) {
      // 觸發依賴
      const dep = getDep(target, key);
      const result = Reflect.set(target, key, value);
      dep.notice();
      return result;
    },
  });
}

const user = reactive({
  age: 19,
});

let double;
effectWatch(() => {
  double = user.age;
  console.log(double);
});

user.age = 20;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章