响应式系统的核心思路
● 需要将对象进行get和set双向绑定使用的是proxy
● 既然是双向绑定那么get的时候就需要进行收集依赖函数 set的时候需要触发依赖
● 收集和触发依赖我们使用的是Map,而Map下每个属性对应的依赖函数使用的是Set来储存
实现思路
- 首先是响应式的代码,使用的就是es6的proxy方法,一下就是大概的一个伪代码实现方式
let obj = {
name: "zs",
age: 15,
};
let handle = {
get(target, key, receiver) {
// 在get中进行track收集依赖函数
return target[key];
},
set(target, key, newValue, receiver) {
target[key] = newValue;
return true;
},
};
let proxyObj = new Proxy(obj, handle);
- 当get的时候需要收集依赖,收集的容器我们使用的是一个weakMap,weakMap下对应的每个对象都是一个Map,然后每个Map属性下对应的就是Set,Set下存放的就是当前属性对应的依赖函数,当我们执行effect的时候会访问proxyObj.name,此时会触发proxy中的get然后进行track,此时bucket中的结构就是{proxyObj:{name:[effect]}}每个对象下的属性对应一个effect函数。
const bucket = new WeakMap();
let activeEffectFn = null;
function track(target, key) {
// 每个对象下面对应的属性都有一个副作用函数
let deps = bucket.get(target);
if (!deps) {
bucket.set(target, (deps = new Map()));
}
let effectFns = deps.get(key);
if (!effectFns) {
deps.set(key, (effectFns = new Set()));
}
effectFns.add(activeEffectFn);
}
let handle = {
get(target, key, receiver) {
// 在get中进行track收集依赖函数
track(target, key);
return target[key];
},
set(target, key, newValue, receiver) {
target[key] = newValue;
return true;
},
};
function effect(fn) {
// 执行effect的fn 会导致执行proxy的get
activeEffectFn = fn;
fn();
}
let obj = {
name: "zs",
age: 15,
};
let proxyObj = new Proxy(obj, handle);
// 执行副作用函数
effect(() => {
console.log(proxyObj.name);
});
- 当set的时候需要触发依赖,此时就需要根据当前对象以及属性找到对应的依赖函数,并触发
const bucket = new WeakMap();
let activeEffectFn = null;
function track(target, key) {
// 每个对象下面对应的属性都有一个副作用函数
let deps = bucket.get(target);
if (!deps) {
bucket.set(target, (deps = new Map()));
}
let effectFns = deps.get(key);
if (!effectFns) {
deps.set(key, (effectFns = new Set()));
}
effectFns.add(activeEffectFn);
}
let handle = {
get(target, key, receiver) {
// 在get中进行track收集依赖函数
track(target, key);
return target[key];
},
set(target, key, newValue, receiver) {
target[key] = newValue;
trigger(target, key);
return true;
},
};
function effect(fn) {
// 执行effect的fn 会导致执行proxy的get
activeEffectFn = fn;
fn();
}
let obj = {
name: "zs",
age: 15,
};
let proxyObj = new Proxy(obj, handle);
// 执行副作用函数
effect(() => {
console.log(proxyObj.name);
});
// 触发set 执行trigger
proxyObj.name = "ls";
最后赋上gitee的链接,里面有大致的响应式设计原理包含computed和watcher从简单到复杂,包含一些注释,以及坑点,如有兴趣课以给个star,感谢