Loading

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;
posted @ 2021-01-25 16:18  lewiskycc  阅读(95)  评论(0编辑  收藏  举报