toRef
作用:创建一个 ref
对象,其 value 值指向另一个对象中的某个属性。
语法:const nane = toRef(person, ' name ')
应用:要将响应式对象中的某个属性单独提供给外部使用时
扩展:toRefs
与 toRef
功能一致,但可以批量创建多个 ref 对象
语法:toRefs(person)
在 Vue3的响应式 中,我们写了一段 js 来模拟 vue3 的响应式
<script>
//源数据
let person = {
name:"张三",
age:18
}
const p = new Proxy(person,{
//有人读取p的某个属性时调用
get(target, p, receiver) {
console.log(`有人读取了p身上的${p}属性`);
//return target[p]
return Reflect.get(target,p)
},
//有人修改、增加p的某个属性时调用
set(target, p, value, receiver) {
console.log(`有人修改了p身上的${p},我要去更新界面了`);
//target[p] = value
Reflect.set(target,p,value)
},
//有人删除p的某个属性时调用
deleteProperty(target, p) {
console.log(`有人删除了p身上的${p},我要去更新界面了`);
//return delete target[p]
return Reflect.deleteProperty(target,p)
}
})
</script>
当修改 p 的属性时,会检测到然后打印相应信息,现在在刚才这段 js 最后增加一句以下代码,然后我们尝试修改 name 属性
let name = p.name
先输出 person 、 p 、name 看下结构,然后修改 name,发现只是修改了 name,p 中的值并未受到影响
然后我们来看下面一段代码,也是我们之前写过的例子,一个人的信息,然后点击按钮进行修改
<template>
<h2>{{ person }}</h2>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>薪资:{{ salary }}K</h2>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">修改年龄</button>
<button @click="salary++">涨薪</button>
</template>
<script>
import {reactive, toRef} from 'vue'
export default {
name: 'Demo',
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20
}
}
})
const name1 = person.name;
console.log("name1", name1);
const name2 = toRef(person.name);
console.log("name2", name2);
return {
person,
name: toRef(person, "name"),
age: toRef(person, "age"),
salary: toRef(person.job.j1, "salary"),
}
}
}
</script>
之前我们 return 中只返回 person,然后取值时使用 person.name、person.age等,如果我们想返回它的某些字段,就需要使用 toRef
,例如返回 name 属性 name:toRef(person, "name")
这样才能让数据依然是响应式的,在模板中可以直接使用 {{name}} 就可以取到值。如果在 return 中直接像以下代码这样写是不行的,因为返回的 name 不是响应式的
错误代码:
return {
name: person.name,
age: person.age,
salary: person.job.j1.salary,
}
上边代码中我们输出了 name1 和 name2,可以看到 name1 仅仅是一个字符串,而 name2 是一个 ObjectRefImpl 。这就解释了为什么直接返回 person.name 不是响应式的了
toRefs
还是上边的代码,我们使用 toRefs,把 person 的第一层拆出来形成了一个对象,我们打印看看
const x = toRefs(person);
console.log(x);
所以刚才的代码可以改为:
<template>
<h2>{{ person }}</h2>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>薪资:{{ job.j1.salary }}K</h2>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">修改年龄</button>
<button @click="job.j1.salary++">涨薪</button>
</template>
<script>
import {reactive,toRefs} from 'vue'
export default {
name: 'Demo',
setup() {
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20
}
}
})
const x = toRefs(person);
console.log(x);
return {
person,
toRefs(person)
}
}
}
</script>