作用:创建一个 ref
对象,其 value 值指向另一个对象中的某个属性。
语法:const name = 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 }}Kh2>
<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,
}
错误代码:
return {
...person
}
上边代码中我们输出了 name1 和 name2,可以看到 name1 仅仅是一个字符串,而 name2 是一个 ObjectRefImpl 。这就解释了为什么直接返回 person.name 不是响应式的了
还是上边的代码,我们使用 toRefs,把 person 的第一层拆出来形成了一个对象,我们打印看看
const x = toRefs(person);
console.log(x);
<template>
<h2>{{ person }}h2>
<h2>姓名:{{ name }}h2>
<h2>年龄:{{ age }}h2>
<h2>薪资:{{ job.j1.salary }}Kh2>
<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>
或者
const {name,age,job} = toRefs(person);
return {
person,
name,
age,
job
}
在 vue2 中我们可以通过给元素添加ref=‘xxx’
,然后在代码中通过refs.xxx
的方式来获取元素。在 vue3 中也可以通过 ref 来获取元素,但不是像刚才说的方式,因为在 vue3 中没有$
和refs
这些东西,我们可以通过一个例子来说明下,添加一个 input,让它自动获取焦点功能:
<template>
<input type="text" ref="inputRef"/>
</template>
<script lang="ts">
import {defineComponent, ref,onMounted} from 'vue';
export default defineComponent({
setup() {
const inputRef = ref<HTMLElement|null>(null);
//页面加载后的生命周期
onMounted(()=>{
inputRef.value && inputRef.value.focus()
})
return{
inputRef
}
}
});
</script>