上文中大概解析了reactive
的实现原理,本文主要解析ref
的实现原理 。
Ref
ref
与reactive
的主要区别在于,ref
可以将 JS 中的基本数据类型(如字符串、布尔值等)与引用类型转换为响应式对象,而reactive
则只能转换引用类型数据。
我们可知ref
执行后返回的是一个RefImpl
类,我们在获取ref
后的值需要通过.value
获取,因此我们可以大概得出RefImpl
的大致结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class RefImpl { constructor(rawValue) { this.__v_isRef = true this._rawValue = rawValue this._value = isObject(rawValue) ? reactive(rawValue) : rawValue } get value() { track(this, 'value') return this._value } set value(newValue) { if (!hasChanged(newValue, this._rawValue)) { this._value = newValue this._rawValue = newValue trigger(this, 'value') } } }
|
创建ref
函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| export const ref = (value) => { return createRef(value) }
function createRef(rawValue) { if (isRef(rawValue)) { return rawValue } return new RefImpl(rawValue) }
function isRef(value) { return !!value.__v_isRef }
|
ShadowRef
shadowRef
的官方解释为ref
的浅层作用形式,可以理解为当shadowRef
传入的是引用类型数据时,只有引用地址变化时才会触发依赖更新,而改变引用类型的属性时不会触发依赖更新,常常用于对大型数据结构的性能优化或是与外部的状态管理系统集成。
我们可以给代码RefImpl
增加一个 shadow 入参,来区分两者的使用:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| function convert(val) { return isObject(val) ? reactive(val) : val }
class RefImpl { constructor(rawValue, shadow = false) { this.__v_isRef = true this._shallow = shadow this._rawValue = rawValue this._value = shadow ? rawValue : convert(rawValue) } get value() { track(this, 'value') return this._value } set value(newValue) { if (!hasChanged(newValue, this._rawValue)) { this._value = newValue this._rawValue = newValue trigger(this, 'value') } } }
export const ref = (value) => { return createRef(value) }
export const shadowRef = (value) => { return createRef(rawValue, true) }
function createRef(rawValue, shadow) { if (isRef(rawValue)) { return rawValue } return new RefImpl(rawValue, shadow) }
|