还不清楚Vue3中toRef和toRefs的区别?有这篇文章就够了

程序员他爱做梦 2024-03-16 10:56:29

首先,我们会有个疑问,为什么需要 toRef 和 toRefs?

toRef 和 toRefs 是 Vue3 中的响应式转换工具函数,它们的存在主要有以下两点原因:

在 Vue 中,直接使用响应式对象的属性可以实现属性的双向绑定和响应式更新。但是有时候需要将某个属性提取出来作为独立的 ref 对象,这样可以在不影响源对象的情况下,对属性进行单独的访问和修改。toRef 函数正是为了解耦属性的关联,将属性转换为一个独立的 ref 对象。Vue 的组件系统中,父组件向子组件传递属性时,需要将这些属性声明为响应式对象。但是,如果直接将整个响应式对象传递给子组件,子组件无法通过解构或者直接访问每个属性。这时,toRefs 函数就可以将整个响应式对象转换为一个普通对象,每个属性都是独立的ref对象,子组件可以轻松解构和访问这些属性。

换句话说,toRef 和 toRefs 就是用来创建响应式的引用的,主要用来取出响应式对象里的属性,或者解构响应式对象,解构出来的属性值依然是响应式属性,如果不用 toRef 或者 toRefs,直接解构会丢失响应式效果。

<script setup> import { reactive } from 'vue'; let info = reactive({ name: 'Echo', age: 26, gender: 'Male', }) // 这样解构会丢失响应式效果 let { name, age, gender } = info;</script>

下面,我们一起看看 toRef 和 toRefs 的用法:

1. toReftoRef 函数可以将一个响应式对象的属性转换为一个独立的 ref 对象。返回的是一个指向源对象属性的 ref 引用,任何对该引用的修改都会同步到源对象属性上。使用 toRef 时需要传入源对象和属性名作为参数。

下面我们一起看一段代码:

<script setup> import { reactive, toRef } from 'vue'; let info = reactive({ name: 'Echo', age: 26, }) let age = toRef(info, 'age'); const updateInfoObjAge = () => { info.age++; } const updateAge = () => { age.value++; }</script><template> <div id="app"> <p>info对象中的age:{{ info.age }}</p> <button @click="updateInfoObjAge">更新info对象中的 age</button> <br /> <p>使用toRef函数转换后的age:{{ age }}</p> <button @click="updateAge">更新 age</button> </div></template>

上面这段代码中:

我们使用 reactive 创建了一个名为 info 的响应式对象,包含 name 和 age 属性。然后使用 toRef 函数将 info 对象的 age 属性转换为一个独立的 ref 对象。接着定义了两个方法 updateInfoObjAge 和 updateAge,分别用于更新 info 对象的 age 属性和 age 引用的值。

从上面的代码中,我们可以看到,age 属性是使用 toRef 函数转换的具有响应式的 ref 属性,当我们更新时,使用 reactive 定义的响应式对象 info 中的 age 也会随着更新。

而且,从开发工具中,我们也可以看到,age 属性是一个具有 ref 响应式的属性。

2. toRefstoRefs 函数可以将一个响应式对象转换为一个普通的对象,该对象的每个属性都是独立的 ref 对象。返回的对象可以进行解构,每个属性都可以像普通的 ref 对象一样访问和修改,而且会保持响应式的关联。toRefs 的使用场景主要是在将响应式对象作为属性传递给子组件时,确保子组件可以正确地访问和更新这些属性。

下面我们一起看一段代码:

<script setup> import { reactive, toRefs } from 'vue'; let info = reactive({ name: 'Echo', age: 26, gender: 'Male', }) let { name, age, gender } = toRefs(info); const update = () => { name.value = 'Julie'; age.value = 33; gender.value = 'Female'; }</script><template> <div id="app"> <p>info对象中的name:{{ info.name }}</p> <p>info对象中的age:{{ info.age }}</p> <p>info对象中的gender:{{ info.gender }}</p> <br /> <p>解构出来的name:{{ name }}</p> <p>解构出来的age:{{ age }}</p> <p>解构出来的gender:{{ gender }}</p> <button @click="update">更新数据</button> </div></template>

上面这段代码中:

首先,使用 reactive 函数创建了一个响应式对象 info,包含了 name、age 和 gender 三个属性,同时设置了初始值。接着,使用 toRefs 函数将 info 对象转换为多个独立的响应式引用对象。然后通过解构赋值,把 name、age 和 gender 三个响应式引用对象分别赋给了相应的变量。最后,添加了一个按钮,点击按钮会触发 update 函数,在 update 函数中,通过修改响应式引用对象的 value 属性来更新数据的值。

从开发工具中,我们可以看到,解构出来的每个属性,都是独立的具有 ref 响应式的属性,因此,我们需要使用 .value 才能访问和修改其值。

3. 相同点toRef 和 toRefs 都用于将响应式对象的属性转换为 ref 对象。转换后的属性仍然保持响应式,对属性的修改会反映到源对象上。不管是使用 toRef 还是 toRefs 将响应式对象转成普通对象,在 script 中修改和访问其值都需要通过 .value 进行。4. 不同点toRef 修改的是对象的某个属性,生成一个单独的 ref 对象。toRefs 修改的是整个对象,生成多个独立的 ref 对象集合。toRefs 适用于在组件传递属性或解构时使用,更加方便灵活,而 toRef 更适合提取单个属性进行操作。

通过上面对 toRef 和 toRefs 函数的了解,你们知道为什么需要 toRef 和 toRefs 了吗?

总结起来就是:在不丢失响应式的前提下,对响应式对象数据进行解构,这样如果在 setup 中返回 toRefs(obj),或者 toRef(obj, 'xxx'),我们就可以在 template 中不使用 obj.xxx 来取值了。

作者:前端小码哥链接:https://juejin.cn/post/7280783758618525732

0 阅读:23

程序员他爱做梦

简介:感谢大家的关注