LOADING

MiniKano的小窝


 

Vue3响应式原理的简单实现

Vue中响应式(拿reactive举例)实现其实是一系列的依赖收集,使用Proxy对传入的对象进行代理监听,返回处理好的代理对象。

//对象的响应式原理
class Depend {
    static activeReactiveFn = null
    static targetMap = new WeakMap()
    constructor() {
        this.reactiveFns = new Set()
    }
    //封装一个获取depend的函数
    static getDepend(target, key) {
        //根据target对象获取map的过程
        let map = Depend.targetMap.get(target)
        if (!map) {
            map = new Map()
            Depend.targetMap.set(target, map)
        }
        //根据key获取depend对象
        let depend = map.get(key)
        if (!depend) {
            depend = new Depend()
            map.set(key, depend)
        }
        return depend
    }

    depend() {
        if (Depend.activeReactiveFn) {
            this.reactiveFns.add(Depend.activeReactiveFn)
        }
    }

    notify() {
        this.reactiveFns.forEach(fn => {
            fn()
        })
    }
}

//封装一个响应式函数
function watchFn(fn) {
    Depend.activeReactiveFn = fn
    fn()
    Depend.activeReactiveFn = null;
}

function reactive(obj) {
    return new Proxy(obj, {
        get(target, key, receiver) {
            const dep = Depend.getDepend(target, key)
            dep.depend()
            return Reflect.get(target, key, receiver)
        },
        set(target, key, newValue, receiver) {
            Reflect.set(target, key, newValue, receiver)
            const dep = Depend.getDepend(target, key)
            dep.notify()
        },
    })
}

//对象的响应式
const obj = reactive({
    name: 'kano',
    age: 18
})

const foo = reactive({
    bar: 111
})

watchFn(() => {
    console.log('obj.name, obj.age---', obj.name, obj.age);
})
watchFn(() => {
    console.log('obj.age---', obj.age);
})

watchFn(() => {
    console.log('foo.bar---', foo.bar);
})

// objProxy.name = 'sadada'
obj.age = 999
foo.bar = 'ds'

getDepend 实际上设置了一个依赖树,如图所示:

obj对应一个weakMap,通过读取weakMap的key(目标对象),获取到对应的属性map,再从属性map中找到依赖,并进行依赖事件触发

点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注