首先回顾下02中存在的问题
- 1.无论读取哪个属性都会将副作用函数activeEffect加入集合中。
get(target,key){
if(activeEffect){
bucket.add(activeEffect);
}
return target[key];
},
setTimeout(() => {
obj.noExsit = "响应式的改变"
},2000)
1.为了解决以上问题,需要建立两种映射关系
- 1.对象 -> key之间的映射关系
- 1.key -> 副作用函数之间的映射关系
2.使用WeakMap建立target和之间的关系
const bucket = new WeakMap()
let depsMap = bucket.get(target)
if(!depsMap){
bucket.set(target,(depsMap = new Map()))
}
2.使用Map建立字段key和副作用函数之间的关系
let deps = depsMap.get(key);
if(!deps){
//Set存放副作用函数
depsMap.set(key,(deps = new Set()))
}
deps.add(activeEffect);
3.完整代码
const data = {text:"hello world"}
//定义存放副作用函数的WeakMap
//WeakMap存放对象 -> Map之间的映射关系
const bucket = new WeakMap()
//对原始数据进行代理
const obj = new Proxy(data,{
//读取值时,将副作用函数加入桶中
get(target,key){
if(!activeEffect){
return target[key]
}
let depsMap = bucket.get(target)
if(!depsMap){
bucket.set(target,(depsMap = new Map()))
}
// Map存放key与副作用函数之间的映射关系
let deps = depsMap.get(key)
if(!deps){
//Set存放副作用函数
depsMap.set(key,(deps = new Set()))
}
deps.add(activeEffect)
return target[key]
},
//改变值时进行操作的拦截
set(target,key,newVal){
target[key] = newVal
const depsMap = bucket.get(target)
if(!depsMap) return
const effects = depsMap.get(key)
//取到该target下key对应的副作用函数Set
effects && effects.forEach(fn =>fn())
}
})
let activeEffect
//通过effect函数来注册响应式函数
function effect(fn){
activeEffect = fn
fn()
}
effect(() => {
console.log("effect run")
document.body.innerText = obj.text
})
setTimeout(() => {
obj.text = "响应式的改变"
},2000)
setTimeout(() => {
obj.noExsit = "响应式的改变"
},2000)
4.总结
setTimeout(() => {
//不会触发响应式,因为const depsMap = bucket.get(target)
obj.noExsit = "响应式的改变"
},2000)