实现vue3源码-isRef & unRef

186 阅读1分钟

isRef & unRef这两个工具函数实现起来很简单,几行代码就可以搞定

isRef

unRef

结语

isRef

测试

期望值这里其实应该字如其名可以看出来

it('isRef', () => {
        const a = 1
        const b = ref(a)
        const user = reactive({
            age: 1
        })
        expect(isRef(a)).toBe(false)
        expect(isRef(b)).toBe(true)
        expect(isRef(user)).toBe(false)

    })

实现

我们只需要在之前的基础之上定义一个变量用来判断就行了,这里我用的是枚举,你们变量也是可以的,不是ref肯定就没有new RefImpl,那么自然这个值就为undefined,我们返回时如果是undefined会与期望值不一致,这里和之前的isReactive的返回可以做同样的双重取反操作

export enum RefFlags {
    IS_REF = '__v_isRef'
}

class RefImpl {
    private _value: any
    public dep
    private _rawValue: any
    public [RefFlags.IS_REF] = true
    constructor(value: any) {
        this._rawValue = value
        // value 为对象时转为reactive包一层
        this._value = convert(value)

        this.dep = new Set()
    }

    get value() {
        trackRefValue(this)
        return this._value
    }

    set value(newValue) {
        if (hasChanged(this._rawValue, newValue)) return
        this._rawValue = newValue
        this._value = convert(newValue)
        triggerEffects(this.dep)
    }
}

export function isRef(ref) {
    return !!ref.__v_isRef
}

unRef

测试

it('unRef', () => {
        const a = 1
        const b = ref(a)
        expect(unRef(a)).toBe(1)
        expect(unRef(b)).toBe(1)

    })

实现

这里利用isRef就可以很轻松的写出来

export function isRef(ref) {
    return !!ref.__v_isRef
}

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

结语

写代码其实也可以看出来先后顺序,做吃出合理规划,之后写代码会变得无比轻松