首先我们先介绍他们是什么???
在 Vue 中,toRef
和toRefs
都是用于处理响应式数据的工具函数。
toRefs
主要用于将一个响应式对象转换为一组响应式引用对象。这样做的好处在于,当你需要解构一个响应式对象时,使用toRefs
可以确保解构后的属性仍然保持响应式。toRef
允许从一个已有的响应式对象中创建一个对特定属性的响应式引用。这个引用会保持与源对象属性的响应式连接,即当源对象的属性值发生变化时,通过toRef
创建的引用也会同步更新。
上面的图片是Vue
官方文档给出的解释,toRefs的实现一定程度是基于toRef上的,下面我们一起通过代码实例来理解这两个APi吧!
🐟toRefs
<template>
<div>
<h2> 姓名:{{ perosn.name }}</h2>
<h2> 年龄:{{ person.age }}</h2>
<button @click="changeName">增加~</button>
<button @click="changeAge">加一</button>
</div>
</template>
<script setup>
import { reactive } from 'vue'
let person = reactive({
name: '张三',
age: 18
})
const changeAge = () => {
person.age += 1
}
const changeName = () => {
person.name += '!'
}
</script>
<style lang="scss" scoped></style>
这段函数定义了一个含有属性name
和age
的Person
对象,并且定义了两个button去修改name
和age
.
如果在这个时候你想使用解构赋值,将person中的name和age提取出来,
let { name, age } = person
是否这个时候我们就可以通过解构出来的age和person,不需要再使用前缀Person去调用了,
<template>
<div>
<h2> 姓名:{{ name }}</h2>
<h2> 年龄:{{ age }}</h2>
<button @click="changeName">增加~</button>
<button @click="changeAge">加一</button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
let person = reactive({
name: '张三',
age: 18
})
let { name, age } = person
const changeAge = () => {
age += 1
console.log(age);
}
const changeName = () => {
name += '!'
console.log(name);
}
</script>
<style lang="scss" scoped></style>
你会发现视图界面并没有更新,但是我在函数里写的console.log(age)
和 console.log(name)
他们的输出会随着函数的调用而改变,说明age
和name
并不是没有改变,而是person.age``person.name
没有改变,因为person
才是响应式对象,而当对一个对象进行解构赋值
时,会创建新的变量
来引用对象的属性值
。如果修改这些新变量的值
,不会直接影响原始对象
。所以就能很好的解释为什么 age,name
的值明明改变了但是为什么视图界面不更新的原因.
这个时候Vue就提供api
让我们去解决这个问题 首先我们介绍toRefs,看下面一段代码
<template>
<div>
<h2> 姓名:{{ name }}</h2>
<h2> 年龄:{{ age }}</h2>
<button @click="changeName">增加~</button>
<button @click="changeAge">加一</button>
</div>
</template>
<script setup>
import { toRefs, reactive } from 'vue'
let person = reactive({
name: '张三',
age: 18
})
let { name, age } = toRefs(person)
const changeAge = () => {
age.value += 1
console.log(age);
}
const changeName = () => {
name.value += '!'
console.log(name);
}
</script>
<style lang="scss" scoped></style>
我们在解构赋值的时候给person
加上了toRefs
,顾名思义,toRefs
就是让解构出来的值变成ref
所定义的响应式数据,所以需要加上value
去修改他的值,console.log()
出来的age
和name
也验证了我们的想法
我们把 let { name, age } = toRefs(person)
这行改为 let x = toRefs(person)
,然后输出一下 x
这个时候我们就可以理解上面说将一个响应式对象转换为一组响应式引用对象
了
🐟toRef
接下来我们介绍一下toRef,toRefs
是把person
这个响应式对象所有的key:value
一次性都取出来,赋予响应式能力,toRef
比他少了一个s
,所以他是创建一个对特定属性的响应式引用,老规矩还是来看一段代码
- 例如,假设有一个响应式对象
person = reactive({ name: '张三', age: 18 })
,可以使用const nameRef = toRef(person, 'name')
创建一个对person
对象中name
属性的引用。
<template>
<div>
<p>姓名:{{ nameRef.value }}</p>
<p>年龄:{{ person.age }}</p>
<button @click="changeName">修改姓名</button>
</div>
</template>
<script setup>
import { reactive, toRef } from 'vue';
const person = reactive({ name: '张三', age: 18 });
const nameRef = toRef(person, 'name');
const changeName = () => {
nameRef.value = '李四';
};
</script>
简单来说就是toRef
适合创建单个属性的响应式引用,这个引用是响应式的,当源对象的该属性发生变化时,通过toRef
创建的引用也会同步更新。
🐟END
toRef
和 toRefs
用于保持解构后的响应式特性,前者创建单个属性的响应式引用,后者创建整个对象所有属性的响应式引用,通过后缀s
区分,有助于简化代码结构。