isRef & unRef
TIP
本篇笔记对应的分支号为: main分支: 6107262
这是两个工具方法。
isRef
用于判断传入的值是否是ref
对象;unRef
用于返回传入ref
对象的value
值。如果传入的不是ref
对象,则将值原样返回。
isRef
老规矩,我们还是先来编写对应的测试用例:
// src/reactivity/__tests__/ref.spec.ts
it('isRef', () => {
const a = ref(1)
const user = reactive({ age: 10 })
expect(isRef(a)).toBe(true)
expect(isRef(1)).toBe(false)
expect(isRef(user)).toBe(false)
})
那我们要如何判断传入的对象是否是个 ref
对象呢?我们可以在 RefImpl
类中定义一个属性 __v_isRef
,用于标识 ref
对象。之后我们对传入的值进行判断,如果有这个属性,那么它就是个 ref
对象:
// src/reactivity/ref.ts
class RefImpl {
private _value: any
private _rawValue: any // 保存原始值,用于 set 阶段对比值是否发生了变化
deps: Set<any>
__v_isRef = true
constructor(value: any) {
this._rawValue = value
this._value = convert(value)
this.deps = new Set()
}
get value() {
// 可以进行 track 时才进行依赖收集
isTracking() && trackEffects(this.deps)
return this._value
}
set value(newValue: any) {
// 如果值没有发生变化,不会触发 trigger
if (hasChanged(this._rawValue, newValue)) {
this._rawValue = newValue
this._value = convert(newValue)
triggerEffects(this.deps)
}
}
}
/**
* 用于判断传入的值是否是 ref
* @param ref
* @returns
*/
export function isRef(ref) {
return !!ref.__v_isRef
}
unRef
话不多说,上测试用例:
// src/reactivity/__tests__/ref.spec.ts
it('unRef', () => {
const a = ref(1)
expect(unRef(a)).toBe(1)
expect(unRef(1)).toBe(1)
})
unRef
的实现其实很简单,只要判断传入的值是否是 ref
对象即可。上面我们已经实现了 isRef
,现在要做的只是返回对应的值就好了:
// src/reactivity/ref.ts
export function unRef(ref) {
return isRef(ref) ? ref.value : ref
}
Loading...