利用proxy手写实现一个简单的响应式

58 阅读1分钟
const bucket = new WeakMap()    //弱引用,防止内存泄漏

//副作用函数
let activeEffect = () => console.log('activeEffect');

// obj -> key -> effect 树形映射关系
let data = {
    name:'xiaoming'
}

//追踪对象key值
function track(target, key){
    if(!activeEffect)  return target[key]
    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 Set()))
    }
    deps.add(activeEffect)
    console.log('track => ', target, key);
}

// 触发对象key值绑定的副作用函数
function trigger(target, key){
    let depsMap = bucket.get(target)
    if(!depsMap)    return
    let effects = depsMap.get(key)
    effects && effects.forEach(effect => effect())
    console.log('trigger => ', target, key);
}

const obj = new Proxy(data, {
    get(target, key){
        track(target, key)
        return target[key]
    },
    set(target, key, newVal){
        target[key] = newVal
        trigger(target, key)
    }
})

console.log('obj.name', obj.name, obj.age); //注册响应事件(副作用函数)

obj.name = 'zhanghua'   //触发响应事件(副作用函数)
obj.age = 18

//输出:
// track =>  { name: 'xiaoming' } name
// track =>  { name: 'xiaoming' } age
// obj.name xiaoming undefined
// activeEffect
// trigger =>  { name: 'zhanghua' } name
// activeEffect
// trigger =>  { name: 'zhanghua', age: 18 } age