学习vue3源码,实现了一下简单的响应式原理。
需要学习掌握Proxy、Reflect、WeakMap、Map、Set
// 全局变量,保存当前依赖的回调
let activeFn = null;
// 依赖收集类
class Dep {
constructor() {
// 避免多次get同一值时重复添加
this.list = new Set();
}
depend() {
if (activeFn) {
// 收集回调函数
this.list.add(activeFn);
}
}
notify() {
// 触发回调
this.list.forEach(fn => fn());
}
}
// 数据结构
const wMap = new WeakMap();
const getDepend = (target, key) => {
// 从weakMap中通过target查到当前对象的数据map
let map = wMap.get(target);
if (!map) {
map = new Map();
wMap.set(target, map);
}
// 从查询到的map中查询当前属性对应的depend
let dep = map.get(key);
if (!dep) {
dep = new Dep();
map.set(key, dep);
}
return dep;
};
// 监听函数
const watch = fn => {
// 保存回调
activeFn = fn;
// 手动执行一次,收集依赖
fn();
activeFn = null;
};
// proxy代理
const reactive = obj => {
return new Proxy(obj, {
get(target, key, receiver) {
// 添加依赖到对应map中
const dep = getDepend(target, key);
dep.depend();
return Reflect.get(target, key, receiver);
},
set(target, key, newValue, receiver) {
Reflect.set(target, key, newValue, receiver);
// 触发对应依赖的回调
const dep = getDepend(target, key);
dep.notify();
},
});
};
const info = reactive({
name: '李四',
age: 20,
});
watch(() => {
console.log('监听info.name改变', info.name);
});
setTimeout(() => {
info.name = '张三';
}, 3000);