持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
toRef
我们先假设这样一个场景,就是有一个对象obj,它有name和age两个属性,这个obj对象是被我们用reactive包裹后的响应式对象。我们如果通过 obj.age
这种方式去改变属性的值,那么视图是会跟着更新的。那么假如我们单独把obj的属性拿出来赋值给某个变量,那么这个变量会是响应式的吗?
let obj = reactive({
name: "mac",
age: 18,
});
console.log(obj) // Proxy {name: 'mac', age: 18}
let age = obj.age;
console.log(age) // 18
很明显,将响应式对象的属性赋值给一个变量,这个变量并不是响应式的。那如果我们希望它也是响应式的呢?有人会想到使用ref来让它变成响应式的,但是这样相当于切断了这个属性和原对象之间的联系,什么意思呢?就是当这个属性发生变化时,在原对象上并不能反映出来了。
那么如果 我们想要把某个响应式对象中的某个属性单独拎出来,保持该属性响应式的同时还不切断它与原对象之间的联系,可以使用toRef来实现这一点。
let age = toRef(obj, 'age')
age.value++ // 变量age的值和obj.age的值都会被影响
这就是toRef的作用了,不过要注意的是,如果原对象不是响应式对象,那么使用toRef搞出来的属性也不会是响应式的。
toRefs
在讲这个的作用前,要先知道一件事情,那就是解构一个reactive包裹后的响应式对象得到的变量,不具有响应式。
上面我们也知道,如果想要将响应式对象中的某个属性单独取出来同时保持其响应式以及和原对象的联系,可以使用toRef,但是有时候一个复杂对象属性可能非常非常多,我们不可能一个一个去使用toRef,这个时候,我们就可以使用toRefs搭配解构来完成了。
function toRefs(object) {
if (!isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`);
}
const ret = isArray(object) ? new Array(object.length) : {};
for (const key in object) {
ret[key] = toRef(object, key);
}
return ret;
}
通过toRefs的源码我们可以知道,它的内部其实是对参数object的每个属性都调用一次toRef。
let {name, age} = toRefs(obj)
// 这样解构出来的name和age依然是响应式的。
toRaw
把响应式对象变成原始对象。
const obj = toRaw(reactiveObj)