0
点赞
收藏
分享

微信扫一扫

vue响应式系统数据劫持

黎轩的闲暇时光 2022-01-11 阅读 43

在vue3中,采用Proxy进行代理,从而实现数据劫持。

依赖收集器

class Dep {
  constructor() {
    this.subscribers = new Set();
  }

  depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect);
    }
  }

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

let activeEffect = null;
function watchEffect(effect) {
  activeEffect = effect;
  effect();
  activeEffect = null;
}

const targetMap = new WeakMap();
function getDep(target, key) {
  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;
}

vue2

function reactive(data) {
  Object.keys(data).forEach(key => {
    const dep = getDep(data, key);
    let value = data[key];

    Object.defineProperty(data, key, {
      get() {
        //收集依赖
        dep.depend();
        return value;
      },
      set(newValue) {
        if (value !== newValue) {
          value = newValue;
          //触发依赖
          dep.notify();
        }
      }
    })
  })

  return data;
}

vue3

function reactive(data) {
  return new Proxy(data, {
    get(target, key) {
      const dep = getDep(target, key);
      //收集依赖
      dep.depend();
      return target[key];
    },
    set(target, key, newValue) {
      const dep = getDep(target, key);
      target[key] = newValue;
      //触发依赖
      dep.notify();
    }
  })
}

使用Proxy进行数据劫持和 Object.defineProperty的区别

1.使用Object.defineProperty进行数据劫持,是对每一个属性进行了劫持,如果新增元素,需要使用$set将新增的元素进行劫持,而使用Proxy代理则是直接代理了整个对象。所以我们在修改数据是,vue2修改原来的数据就可以进行响应式,在vue3中需要修改的是我们的代理对象proxy。
2.Proxy能够观察的类型比Object.defineProperty更丰富,包括has,delete等操作。
3.Proxy是新标准。但是不兼容IE。

举报

相关推荐

0 条评论