首先回顾下响应式的原理
- 在get操作时,将响应式函数(能够修改页面的副作用函数)加入到集合中。
- 在set操作时,将函数从集合中拿出并执行副作用函数,达到修改页面数据的实现效果。
在01中,我们硬编码了响应式函数,一旦该函数不是effect了,该响应式系统就不能正常工作。所以需要在以下两处优化代码。
get(target,key){
bucket.add(effect)
return target[key]
}
function effect(){
document.body.innerText = obj.text
}
1.改造effect函数
首先定义一个全局变量,每次执行effect函数时将传入的fn赋值给activeEffect,此时无论fn是匿名函数还是普通函数。
let activeEffect;
function effect(fn){
activeEffect = fn;
fn()
}
2.改造代理的get
当读取代理对象的属性时,加入集合的不再是effect,而是全局变量activeEffect
get(target,key){
if(activeEffect){
bucket.add(activeEffect);
}
return target[key];
},
3.完整源码
const data = {text:"hello world"};
const bucket = new Set();
const obj = new Proxy(data,{
get(target,key){
if(activeEffect){
bucket.add(activeEffect);
}
return target[key];
},
set(target,key,newVal){
target[key] = newVal;
bucket.forEach(fn => fn());
return true;
}
})
let activeEffect;
function effect(fn){
activeEffect = fn;
fn()
}
effect(() => {
console.log("effect run");
document.body.innerText = obj.text;
})
setTimeout(() => {
obj.text = "响应式的改变"
},2000)
4.总结:没有在副作用函数和目标字段(如text)间建立联系
- 1.无论读取哪个属性都会将副作用函数activeEffect加入集合中。
- 2.只要触发set都会执行副作用函数。
setTimeout(() => {
obj.noExsit = "响应式的改变"
},2000)