05-ref

122 阅读1分钟

ref & toReactive

  • 接受一个内部值并返回一个响应式且可改变的ref对象。ref对仅有一个.valueproperty,指向该内部值。
  • 如果将对象分配为 ref 值,则它将被 reactive 函数处理为深层响应式对象。
function toReactive(value) {
    return isObject(value) ? reactive(value) ? value
}
class  RefImpl {
    public _value = null
    public dep = new Set() // 收集副作用
    public readonly __v_isRef = true // 标识 ref
    constructor(public rawValue){
        // rawValue 用于保存 没有被 reactive 响应式代理前的值,用于在 set 时 进行新旧比较
        this._value = toReactive(this.rawValue)
    }
    get value () {
       trackEffects(this.dep)
        return this._value
    }
    set value (newValue) {
        if(newValue !== this.rawValue) {
            this._value = toReactive(newValue)
            this.rawValue = newValue
            triggerEffect(this.dep)
        }
      
    }
}
function ref(value) {
    return new RefImpl(value)
}

unref & isRef

  • 如果参数是一个ref,则内部犯规参数本身。这是 val = isRef(val) ? val.value : val 的语法糖函数
function isRef(value) {
    return !!(value && value?.__v_isRef)
}

function unref(ref) {
    return isRef(ref) ? ref.value : ref
}

toRef & toRefs

  • 可以用来为源响应式对象上的某个property新创建一个ref。然后,ref可以被传递,它会保持对其源property的响应式连接。
class ObjectImpl {
    public __v_isRef = true
    constructor(public _object,public _key) {}
    get value() {
        return this._object[this._key]
    }
    set value(newValue) {
        this._object[this._key] = newValue
    }
}

function toRef(object,key) {
    return new ObjectImpl(object,key)
}

function toRefs(object) {
   let ret = isArray(object) ? new Array(object.length) : {}
   for(let key in object) {
      ret[key] = toRef(object,key) 
   }
   return ret
}

proxyRefs

  • 在template 模板中使用 ref,不需要.value 就能取到值,用的就是proxyRef
const proxyRefs = (objectWithRef) {
    if(isReactive(objectWithRef)){
        return objectWithRef
    }
    cont p = new Proxy(objectWithRef, {
        get(target,key,receiver) {
            return unref(Reflect(target,key,receiver))
        },
        set(target,key,value,receiver) {
            const oldValue = target[key]
            if(isRef(oldValue)&& !isRef(value)) {
              oldValue.value = value
            }else {
                return Reflect.set(target,key,value,receiver)
            }
        }
    })
    
    return p
}