let set = new Set();
function effect(fn) {
function effectFn() {
fn();
}
set.add(fn.toString());
effectFn();
}
effect(() => console.log(1));
effect(() => console.log(1));
console.log(set);
涉及修改的代码如下:
function track(target, key) {
if (!effectStack.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 Map));
//以函数文本作为key,达到去重效果
deps.set(effectStack.source, effectStack.activeEffect());
effectStack.activeEffect().deps.push(deps);
}
function trigger(target, key) {
let depsMap = bucket.get(target);
if (!depsMap) return;
let effectsToRun = new Map(depsMap.get(key));
effectsToRun.forEach(fn => fn());
}
function effect(fn) {
function effectFn() {
cleanup(effectFn);
effectStack.push(effectFn);
fn();
effectStack.pop();
}
//存储函数文本
effectFn.source = fn.toString();
effectFn.deps = [];
effectFn();
}
在进行嵌套定义effect时,如果多次修改外部effect中使用的响应式数据,会间接调用内部effect。
effect(fn)
会将fn
包装为effectFn
obj.foo
进行重新绑定时,会导致内部的依赖再次绑定bucket
的数据结构中的Set无法对effectFn
进行去重,也就导致注册多个重复的依赖。程序的输出结果为:
在对内部的响应式数据进行修改时,触发了三个
effectFn
,其中有初始化的1个,两次对obj.foo
进行修改时,间接添加的effectFn
。 在我个人看来,应该只需要执行一个effectFn
,而不是三个,不知道是本意如此,还是意外的BUG。 如果是BUG,我想到了一个不是很好解决的方法:通过将函数转为string来判断是否为相同的函数。例如:涉及修改的代码如下:
以上是个人看法,如有错误,还请霍老师指正😳。