手写 shallowRef 和 ref

239 阅读1分钟

shallowRef

一般 ref 用来创建基本数据,reactive 用来创建对象,如果把对象传入 ref,也会进行 reactive 的处理

function shallowRef(target){
    return {
        _value:target,
        get value(){
            console.log('get')
            return this._value
        },
        set value(val){
            console.log('set')
            this._value=val
        }
    }
}

const data=shallowRef({
    name:'jzhu',
    car:{
        color:'red'
    }
})

data.value.name='frank'        // get
data.value.car.color='green'   //get

第二个结果表明 shallowRef 只是对外层属性进行拦截

而 ref 的实现也相差无几,但最重要的是我们需要 reactive,如果传入对象的话

function ref(target){
    target=reactive(target)  // 未实现
    return {
        _value:target,
        get value(){
            console.log('get')
            return this._value
        },
        set value(val){
            console.log('set')
            this._value=val
        }
    }
}

reactive 实现如下

const handler={
    get(target,key){
        console.log('get')
        return Reflect.get(target,key)
    },
    set(target,key,val){
        console.log('set')
        return Reflect.set(target,key,val)
    },
    deleteProperty(target,key){
        console.log('delete')
        return Reflect.deleteProperty(target,key)
    }
}
function reactive(target){
    if(target && typeof target==='object'){
        if(Array.isArray(target)){
            target.forEach((item,index)=>{
                target[index]=reactive(item)
            })
        }else{
            Object.keys(target).forEach(key=>{
                target[key]=reactive(target[key])
            })
        }
        return new Proxy(target,handler)
    }else{
        return target
    }
}

其实无论是 ref 还是 reactive,都要使用 Proxy 进行拦截

ref 在使用时需要取其 value 属性,说明 ref 初始化的值存在 ref 的返回值(对象)中,所以我们需要存下初始化时传入的对象