实现 ref 函数
isRef
判断一个数据是否是用 ref 声明的响应式数据
单测 1 2 3 4 5 6 7 8 9 10 11 ... it ('isRef' , () => { const a = ref (1 ) const user = reactive ({ age : 1 }) expect (isRef (a)).toBe (true ) expect (isRef (1 )).toBe (false ) expect (isRef (user)).toBe (false ) })
实现单测 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ... class RefImpl { private _value : any public dep private _rawValue : any public __v_isRef = true constructor (value ) { this ._rawValue = value this ._value = convert (value) this .dep = new Set () } get value () { trackRefValue (this ) return this ._value } set value (newVal ) { if (hasChanged (newVal, this ._rawValue )) { this ._rawValue = newVal this ._value = convert (newVal) triggerEffects (this .dep ) } } } export const isRef = ref => !!ref.__v_isRef ;
实现 unRef 函数
unRef
省略了 ref.value 繁琐操作,直接获取值
单测 1 2 3 4 5 6 7 ... it ('unRef' , () => { const a = ref (1 ) expect (unRef (a)).toBe (1 ) expect (unRef (1 )).toBe (1 ) })
实现单测 1 2 3 4 ... export const unRef = ref => (isRef (ref) ? ref.value : ref)
实现 proxyRefs 函数
proxyRefs
主要用来在 vue3 中 template 的 setup 去转换一下 ref 类型,省去了 .value 繁琐操作。 本质就是一个 proxy,代理了一个取值,修改的功能,取值功能就是一个 unRef,修改的时候,需要判断被修改属性是否是 ref 类型,如果是 ref 类型,且新值为非 ref 类型就是 替换掉被修改属性的 .value;如果被修改属性和新值都为 ref 类型,则直接替换掉被修改属性即可。
单测 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ... it ('proxyRefs' , () => { const user = { age : ref (10 ), name : 'qiuSu' } const proxyUser = proxyRefs (user) expect (user.age .value ).toBe (10 ) expect (proxyUser.age ).toBe (10 ) expect (proxyUser.name ).toBe ('qiuSu' ) proxyUser.age = 20 expect (proxyUser.age ).toBe (20 ) expect (user.age .value ).toBe (20 ) })
实现单测 1 2 3 4 5 6 7 8 9 10 11 12 13 ... export const proxyRefs = objectWithRefs => { return new Proxy (objectWithRefs, { get (target, key ) { return unRef (Reflect .get (target, key)) }, set (target, key, val ) { if (isRef (target[key]) && !isRef (val)) return (target[key].value = val) else return Reflect .set (target, key, val) } }) }