乐趣区

关于javascript:40-行代码简单实现vue3的响应系统

指标

实现 vue-next 响应式模块中的两个 API : reactiveeffect

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
}
退出移动版