前言
从这里开始进行vue3源码的阅读,通过vue设计与实现结合源码完成vue3源码的整体解读。
本章了解一下vue3的响应式收集依赖和触发依赖。
流程
这里用代码实现一下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响应式对象的一个步骤图,后续会为大家逐渐完善,谢谢