vue3响应式监听原理

212 阅读2分钟

前言

从这里开始进行vue3源码的阅读,通过vue设计与实现结合源码完成vue3源码的整体解读。

本章了解一下vue3的响应式收集依赖和触发依赖。

流程

QQ截图20220402114016.png

这里用代码实现一下track、trigger以及effect副作用函数

track用来收集依赖

trigger用来执行依赖

// 依赖桶
const bucket = new WeakMap();

// 临时储存effectFn
let activeEffect;

function track (target, key) {
  if (!activeEffect) return;
  let depsMap = bucket.get(target);
  if (!depsMap) {
    bucket.set(target, (depsMap = new Map()));
  }
  let deps = depsMap.get(key);
  if (!deps) {
    depsMap.set(key, (deps = new Set()));
  }

  deps.add(activeEffect);
}

function trigger (target, key, type, newVal) {
  const depsMap = bucket.get(target);
  if (!depsMap) return;
  const effects = depsMap.get(key);

  effects.forEach(effectFn => {
      effectFn && effectFn();
  })
}

function effect (fn) {
    const effectFn = () => {
        activeEffect = effectFn;
        fn();
    }
    effectFn();
}

这样我们就可以用vue3中响应式对象监听的proxy来实现一个触发和收集依赖了

const proxy = new Proxy({key: 1}, {
    get (target, key) {
        track(target, key);
        return target[key];
    },
    set (target, key, newVal) {
        target[key] = newVal;
        
        trigger(target, key);
        
        return true;
    }
})

现在来通过步骤解析了解一下执行的流程

let num = 0;
effect(() => {
    num = proxy.key
    console.log(num)
})

proxy.key = 2

// 首先effect会自动执行
// 监听到proxy.key为代理获取
// 这时会触发track将数据储存到桶中
// 先在桶的结构是   bucket = {{key: 1} => Map({'key' => Set(effectFn)})}
// 当proxy.key = 2时
// 监听proxy为set所以会触发trigger
// 这时会将桶里的数据取出并执行effect传入的函数
// 控制台总共会输出两次数据 分别为 1 和 2

这样我们就实现了vue3中的响应式监听的原理

当然,这只是最基础的样子,主要是通过一个简单的功能来了解一下vue3中的监听操作

vue3中的响应式监听比这还复杂的多,里面还有监听对象删除、for in 、for of、等一系列的操作

后面会逐步的来实现vue3中reactive模块以及组件更新以及模板渲染等操作

下面是实现vue3响应式对象的一个步骤图,后续会为大家逐渐完善,谢谢

QQ截图20220402135720.png