Vue2和Vue3的响应式原理

Posted 还是不会呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue2和Vue3的响应式原理相关的知识,希望对你有一定的参考价值。

Vue2和Vue3的响应式原理

这个其实在Vue2&Vue3专栏的源码学习部分,已经实现过,但是当时还是对部分的数据结构存在不明确的部分,比如说Proxy类,Reflect对象,Set数据结构,就没有运用这部分知识点,用了也不明确。那么这篇文章,可以在之前实现得基础上做出优化,利用ES6的新知识点

依赖保存的数据结构

obj1
obj2
key1
key2
key1
key2
整个响应式系统 WeakMap
obj1对应的Map
obj2对应的Map
key1对应得依赖 Set
key1对应得依赖 Set
key1对应得依赖 Set
key1对应得依赖 Set

vue3实现原理

let activeFn = null;

class Depend {
  constructor() {
    this.depend = new Set();
  }
  addDep() {
    if (activeFn) {
      this.depend.add(activeFn);
    }
  }
  notify() {
    this.depend.forEach((fn) => {
      fn();
    });
  }
}

function watchFn(fn) {
  activeFn = fn;
  fn();
  activeFn = null;
}

let weakMap = new WeakMap();
function getDep(raw, key) {
  let dep = weakMap.get(raw);
  if (!dep) {
    dep = new Map();
    weakMap.set(raw, dep);
  }
  let deep = dep.get(key);
  if (!deep) {
    deep = new Depend();
    dep.set(key, deep);
  }
  return deep;
}

function reactive(raw) {
  return new Proxy(raw, {
    get(target, key, receiver) {
      const deep = getDep(target, key);
      deep.addDep();
      return Reflect.get(target, key, receiver);
    },
    set(target, key, newValue, receiver) {
      Reflect.set(target, key, newValue, receiver);
      const deep = getDep(target, key);
      deep.notify();
    },
  });
}

// 测试代码
const info = reactive({
  name: "fzb",
  age: 21,
});

watchFn(function () {
  console.log(info.name, "----------------1");
});
watchFn(function () {
  console.log(info.name, "----------------2");
});

watchFn(function () {
  console.log(info.age, "----------------1");
});

info.name = "gj";
info.age++;

vue2实现原理

let activeFn = null;

class Depend {
  constructor() {
    this.depend = new Set();
  }
  addDep() {
    if (activeFn) {
      this.depend.add(activeFn);
    }
  }
  notify() {
    this.depend.forEach((fn) => {
      fn();
    });
  }
}

function watchFn(fn) {
  activeFn = fn;
  fn();
  activeFn = null;
}

let weakMap = new WeakMap();
function getDep(raw, key) {
  let dep = weakMap.get(raw);
  if (!dep) {
    dep = new Map();
    weakMap.set(raw, dep);
  }
  let deep = dep.get(key);
  if (!deep) {
    deep = new Depend();
    dep.set(key, deep);
  }
  return deep;
}

function reactive(raw) {
  Object.keys(raw).forEach((key) => {
    let value = raw[key];
    let deep = getDep(raw, key);
    Object.defineProperty(raw, key, {
      get() {
        deep.addDep();
        return value;
      },
      set(newValue) {
        value = newValue;
        deep.notify();
      },
    });
  });
  return raw;
}

// 测试代码
const info = reactive({
  name: "fzb",
  age: 21,
});

watchFn(function () {
  console.log(info.name, "----------------1");
});
watchFn(function () {
  console.log(info.name, "----------------2");
});

watchFn(function () {
  console.log(info.age, "----------------1");
});

info.name = "gj";
info.age++;

以上是关于Vue2和Vue3的响应式原理的主要内容,如果未能解决你的问题,请参考以下文章

Vue2和Vue3的响应式原理

vue2与vue3响应式原理

Vue2和Vue3的响应式原理

vue2的响应式原理学“废”了吗?继续观摩vue3响应式原理Proxy

Vue2与Vue3的响应式原理-区别讲解

Vue3官网-高级指南(十七)响应式计算`computed`和侦听`watchEffect`(onTrackonTriggeronInvalidate副作用的刷新时机`watch` pre)(代码片段