ref的作用
主要是由于proxy代理的是引用数据类型,而不能代理基本数据类型,而一些基本数据类型也需要进行响应式操作,从而引入了ref来做基本数据类型的响应式
思路:
创建一个ref的对象用于包装基本数据类型,通过一个内部的 value 属性来存储原始值,主要也是在get的时候进行依赖收集(可看reactive effect);在set的时候进行找到对应的effect副作用函数,触发更新
示例
class RefImpl {
public __v_isRef = true // ref标识
public _value // 用来保存ref的值
public dep //收集对应的effect
constructor(public rawValue) {
this._value = toReactive(rawValue)
}
get value() {
trackRefValue(this)//依赖收集
return this._value
}
set value(newValue) {
if (newValue !== this.rawValue) {
this.rawValue = newValue
this._value = newValue
triggerRefValue(this)//触发更新
}
}
}
toRef toRefs作用
将reactive中的属性直接结构出来会导致该属性丧失响应式,toRef就是将该属性转化为ref,使得该变量依然保持响应性,toRefs的作用则是批量进行上述此操作。
- toRef: 用于将 reactive 对象中的某个属性转换为一个 ref,包装成一个响应式对象,从而单独解构出来后依然能保持响应性。
- toRefs: 则是对 toRef 的批量封装,对对象中的每个属性都进行上述转换,确保对象整体在解构后每个属性都能独立地响应变化。
示例
export function toRef(object, key) {
return new ObjectRefImpl(object, key)
}
class ObjectRefImpl {
public __v_isRef = true
constructor(public _object, public _key) {
}
get value() {
return this._object[this._key]
}
set value(newValue) {
this._object[this._key] = newValue
}
}
export function toRefs(object) {
const result = {}
for (const key in object) {
result[key] = toRef(object, key)
}
return result
}
补充
- 使用 toRef 解构后的值进行修改,其本质上就是直接修改了 reactive 对象中对应的属性