指标
实现 vue-next 响应式模块中的两个 API : reactive
、effect
var obj = reactive({
name: 'Vic',
haha: {num: 0}
})
effect(() => {console.log('打印消息:obj.name', obj.name)
})
effect(() => {console.log('打印消息:obj.haha.num', obj.haha.num)
})
obj.name = 'qiu'
obj.haha.num = 9
// output Vic
// output 0
// output qiu
// output 9
代码实现
const targetMap = new WeakMap()
let activeEffect = null
const handlers = {get(target, key, receiver) {const res = Reflect.get(target, key, receiver)
tarck(target, key)
return typeof res === 'object'
? reactive(res)
: res
},
set(target, key, value, receiver) {const res = Reflect.set(target, key, value, receiver)
trigger(target, key)
return res
}
}
function reactive(target) {return new Proxy(target, handlers)
}
function tarck(target, key) {if (!activeEffect) return
let depsMap = targetMap.get(target)
if (!depsMap) targetMap.set(target, (depsMap = new Map()))
let deps = depsMap.get(key)
if (!deps) depsMap.set(key, (deps = new Set()))
if (!deps.has(activeEffect)) deps.add(activeEffect)
}
function trigger(target, key) {targetMap.get(target).get(key).forEach(fn => fn())
}
function effect(fn) {
activeEffect = fn
fn()
activeEffect = null
}