vue3响应式工具 toRefs() 和 toRef()

news2024/9/21 0:46:12

前言

直接解构响应式对象的属性进行赋值给新的变量,会导致新变量失去响应式。
当修改新变量的值时,不会触发原始响应式对象的更新,从而在模板中也不会有相应的视图更新。

示例:

<template>
  <div>
    <p>姓名: {{ person.name }}</p>
    <p>年龄: {{ person.age }}</p>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';

// person是响应式对象
const person = reactive({
  name: '张三',   // person.name 是响应式的
  age: 36         // person.age 是响应式的
});
// person.name = '李四' 会触发响应式更新
// person.age = 24 会触发响应式更新

// 解构赋值
let { name, age } = person
// 语句相当于执行:let name = person.name; let age = person.age
// 修改name、age,person的name属性、age属性不会改变

const changeName = () => {
  name += '哈'  // name改变了,没有触发响应式更新
  console.log(`name: ${name}, person.name: ${person.name}`); 
}
const changeAge = () => {
  age ++   // age改变了,没有触发响应式更新
  console.log(`age: ${age}, person.age: ${person.age}`)  
}
</script>

控制台打印结果:
在这里插入图片描述
let { name, age } = person 相当于执行let name = person.name; let age = person.age,使用方法changeNamechangeAge修改nameage,本质上修改的是使用let声明的name变量、age变量,personname属性、age属性不会改变。因此不会触发响应式更新。

从响应式的数据person直接解构出来的nameage不是响应式的。

在 Vue 3 中,toRefs()toRef()都是用于处理响应式对象的工具函数,它们的作用是将响应式对象中的属性转换为独立的响应式引用。主要用来取出响应式对象里的属性,或者解构响应式对象。

toRefs()

toRefs()将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。

使用toRefs()函数来保持解构后的属性的响应式:

<template>
  <div>
    <p>姓名: {{ person.name }}</p>
    <p>年龄: {{ person.age }}</p>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>
<script setup lang="ts">
import { reactive, toRefs } from 'vue';

const person = reactive({
  name: '张三',
  age: 36
});

// 将响应式对象解构为响应式引用
let { name, age } = toRefs(person)
// 使用toRefs解构后,name、age都变成了使用ref()定义的响应式引用,指向原始响应式对象中的属性。

console.log('toRefs(person):', toRefs(person))
console.log('解构后的name:', name)
console.log('解构后的age:', age)

const changeName = () => {
  name.value += '哈'  // name改变了,触发响应式更新
  console.log(`name: ${name.value}, person.name: ${person.name}`); 
}
const changeAge = () => {
  age.value ++   // age改变了,触发响应式更新
  console.log(`age: ${age.value}, person.age: ${person.age}`); 
}
</script>

let { name, age } = toRefs(person);使用toRefs()将响应式对象person解构为nameage两个响应式引用:
在这里插入图片描述
通过 toRefs()person 对象解构后得到的 nameage 是响应式引用,它们与原始对象 person 的对应属性保持着响应式的关联。
nameage的修改会触发响应式更新,并且会同步到原始的响应式对象person中:
在这里插入图片描述
在模板中,可以使用响应式引用来访问和显示特定属性的值:

<template>
  <div>
    <p>姓名: {{ name }}</p>
    <p>年龄: {{ age }}</p>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>

在模板中直接使用 nameage 与使用 person.nameperson.age 的效果是一样的,都能正确地展示响应式数据,并且在数据发生变化时自动更新视图。

toRefs() 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref,请改用 toRef()

toRef()

toRef()创建一个特定属性的响应式引用

  • toRef()接收一个响应式对象和一个属性名作为参数,并返回一个响应式引用,指向原始响应式对象中的特定属性。
  • toRefs()不同,它只创建一个特定属性的响应式引用。

示例:

<template>
  <div>
    <p>姓名: {{ name }}</p>
    <p>年龄: {{ age }}</p>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>
<script setup lang="ts">
import { reactive, toRef } from 'vue';

const person = reactive({
  name: '张三',
  age: 36
});

// 创建了一个名为 name 的响应式引用,指向 person 对象中的 name 属性
let name = toRef(person, 'name')
console.log(name)
// 创建了一个名为 age 的响应式引用,指向 person 对象中的 age 属性
let age = toRef(person, 'age')
console.log(age)

const changeName = () => {
  name.value += '哈'  // name改变了,触发响应式更新
  console.log(`name: ${name.value}, person.name: ${person.name}`); 
}
const changeAge = () => {
  age.value ++   // age改变了,触发响应式更新
  console.log(`age: ${age.value}, person.age: ${person.age}`); 
}
</script>

控制台打印结果:
在这里插入图片描述

toRef()可以将值、refs 或 getters 规范化为 refs (3.3+)

  • toRef()可以接受一个普通的值,并将其包装成一个响应式引用。
  • 也可以接受一个已有的ref对象,直接返回这个ref对象。
  • 还可以接受一个getter函数,将其返回值包装成一个响应式引用。
  • 返回值:返回一个新的ref对象,该对象指向原始响应式对象中的特定属性或者普通值、getter函数的返回值。

将普通值转换为响应式引用

<template>
  <div>
    <p>count: {{ count }}</p>
    <p>countRef: {{ countRef }}</p>
    <button @click="changeCount">点击修改count</button>
    <button @click="changeCountRef">点击修改countRef</button>
  </div>
</template>
<script setup lang="ts">
import { toRef } from 'vue';

// 定义一个普通变量count,初始值为 10
let count = 10
console.log('count: ',  count)

// 通过toRef转换把普通变量count为响应式引用countRef
let countRef = toRef(count)
console.log('countRef: ', countRef)

const changeCount = () => {
  count++   // count改变了,但不会触发响应式更新
  console.log('changeCount()---count:', count)
}
const changeCountRef = () => {
  // 修改响应式引用countRef.value的值,触发响应式更新
  // 同时也会更新原始的普通变量count的值
  // 会触发count、countRef的响应式更新
  countRef.value++ 
  console.log('changeCountRef()---countRef: ', countRef)
}

</script>

执行changeCountcount的值改变了,但页面显示仍然是初始值10,不会触发响应式更新:
在这里插入图片描述
执行changeCountRef,通过修改响应式引用countRef.value的值,触发响应式更新。会触发countcountRef的响应式更新:
在这里插入图片描述
在这个例子中,toRef()将普通的数字值10转换为一个响应式引用countRef。对countRef.value的修改会影响到原始的值,并且在响应式系统中触发更新。


处理已有ref对象

import { ref, toRef } from 'vue';

const originalRef = ref(20);
const newRef = toRef(originalRef);

如果将一个已有的ref对象传递给toRef(),它会直接返回这个ref对象。


使用getter函数

import { reactive, toRef } from 'vue';

const state = reactive({
  count: 0,
});

const getCount = () => state.count;
const countRef = toRef(state, getCount);

使用getter函数getCount来获取响应式对象state中的count属性的值。toRef()将这个getter函数的返回值包装成一个响应式引用countRef。当state.count的值发生变化时,countRef.value也会相应地更新。

toRefs()toRef() 的区别

  1. 应用场景不同
    • toRefs()适用于需要将整个响应式对象解构为多个独立响应式引用的情况,通常在函数参数传递或在多个地方使用响应式对象的不同属性时很有用。
    • toRef()适用于只需要创建单个属性的响应式引用的情况,比如在特定场景下只关注一个属性的变化。
  2. 返回值不同
    • toRefs()返回一个包含多个响应式引用的对象(批量解构)。
    • toRef()返回一个单个的响应式引用(一个一个的操作)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2051922.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

垂直行业数字化表现抢眼 亚信科技全年利润展望乐观

大数据产业创新服务媒体 ——聚焦数据 改变商业 2024年8月14日&#xff0c;亚信科技控股有限公司&#xff08;股票代码&#xff1a;01675.HK&#xff09;公布了公司截至2024年6月30日的中期业绩。 财报数据显示&#xff0c;2024年上半年&#xff0c;亚信科技的营业收入为人民币…

Java巅峰之路---进阶篇---面向对象(一)

static关键字 介绍 static表示静态&#xff0c;是java中的一个修饰符&#xff0c;可以修饰成员方法&#xff0c;成员变量。 其中&#xff0c;被static修饰的成员变量&#xff0c;叫做静态变量&#xff1b;被static修饰的成员方法&#xff0c;叫做静态方法。 静态变量 调用…

水凝胶和皮肤再生有关系?那它是什么玩意儿?

大家好&#xff0c;今天我们来聊聊皮肤再生与水凝胶的关系。这篇《Hydrogel-Based Skin Regeneration》是发表于《International Journal of Molecular Sciences》上的一篇文章。皮肤作为人体最大的器官&#xff0c;其伤口愈合至关重要&#xff0c;但传统治疗方法有局限性。组织…

数据结构(Java):揭开二叉搜索树删除机制的奥秘

目录 1、二叉搜索树 1.1 概念 2、代码模拟实现 2.1 插入操作 2.2 查找操作 2.3 &#x1f31f;删除操作&#x1f31f;&#xff08;难点&#xff09; 2.3.1 要删除节点的左子树为空 2.3.2 要删除节点的右子树为空 2.3.3 要删除节点的左右子树均不为空 2.3.4 删除操作代码…

认知杂谈17

今天分享 有人说的一段争议性的话 I I 男人撑起一片天&#xff0c;背后是默默的坚守与承担 说起生孩子这事儿啊&#xff0c;对大多数男同胞来讲&#xff0c;那真是又温馨又充满挑战。要当爸爸了&#xff0c;这意味着责任重大&#xff0c;心里期待满满&#xff0c;一方面得…

函数图像绘制小工具

函数图像绘制小工具 文章说明核心代码效果展示源码下载 文章说明 方便绘制一些数学的基础图象&#xff0c;制作该款小工具&#xff0c;不过尚为雏形阶段&#xff0c;等待后续逐步完善 核心代码 采用canvas绘图实现&#xff0c;核心代码如下 <script setup> import {onMou…

公开数据库汇总及下载(1)-TCGA

文章目录 1. 常用数据库2. TCGA数据下载2.1 TCGA介绍2.2 数据类型详解2.3 TCGA数据等级2.4 TCGA网页筛选页面介绍2.5 各文件每个字段的含义2.6 biospecimen IDs介绍(样本ID)2.7 下载代码 参考文件 本文的内容介绍、代码下载主要参考了网上多个文件汇总而成&#xff0c;本文仅作…

深度学习基础—Dropout正则化(随机失活正则化)

1.Dropout正则化 Dropout正则化&#xff1a;网络中每一个神经元节点都有一定概率保留或消除&#xff0c;从而下较小规模的网络。 假设上图网络存在过拟合&#xff0c;Dropout正则化的做法就是遍历每一个节点&#xff0c;对该节点以一定的概率保留或删除&#xff0c;从而简化网络…

C语言 | Leetcode C语言题解之第347题前K个高频元素

题目&#xff1a; 题解&#xff1a; struct hash_table {int key;int val;// 查看 https://troydhanson.github.io/uthash/ 了解更多UT_hash_handle hh; };typedef struct hash_table* hash_ptr;struct pair {int first;int second; };void swap(struct pair* a, struct pair*…

【C++】udp通信协议详解和示例

前言 UDP&#xff08;‌User Datagram Protocol&#xff0c;‌用户数据报协议&#xff09;‌是一种无连接的、‌不可靠的、‌面向数据报的传输层协议。‌它广泛应用于需要高实时性且对数据传输可靠性要求不高的场景&#xff0c;‌如实时音视频传输、‌在线游戏等。‌本文将详细…

Python做统计图之美

Python数据分析可视化 案例效果图 import pandas as pd import matplotlib.pyplot as plt import matplotlib# 数据 data {"房型": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],"住宅类型": ["普通宅", "普通宅", "普通宅", &q…

JUC6-共享模型之不可变

目录 日期转换的问题 问题提出 思路&#xff1a;同步锁 思路&#xff1a;不可变 不可变设计 final的使用 保护性拷贝 享元模式 概述 体现 包装类 String串池 BigDecimal BigInteger DIY 原理&#xff1a;final 无状态 日期转换的问题 问题提出 下面的代码在运…

python井字棋游戏设计与实现

python实现井字棋游戏 游戏规则&#xff0c;有三个井字棋盘&#xff0c;看谁连成的直线棋盘多谁就获胜 棋盘的展现形式为 棋盘号ABC和位置数字1-9 输入A1 代表在A棋盘1号位数下棋 效果图如下 部分源码如下&#xff1a; 卫星工纵浩 白龙码程序设计&#xff0c;点 代码获取 …

Stability AI发布了单目视频转4D模型的新AI模型:Stable Video 4D

开放生成式人工智能初创公司Stability AI在3月发布了Stable Video 3D&#xff0c;是一款可以根据图像中的物体生成出可旋转的3D模型视频工具。Stability AI在7月24日发布了新一代的Stable Video 4D&#xff0c;增添了赋予3D模移动作的功能。 Stable Video 4D能在约40秒内生成8…

DBAPI如何用SQL将多表关联查询出树状结构数据(嵌套JSON格式)

场景描述 假设数据库中有3张表如下&#xff1a; 客户信息表 订单表 订单详情表 一个客户有多个订单&#xff0c;一个订单包含多个产品信息&#xff0c;客户-订单-产品就构成了3级的树状结构&#xff0c;如何查询出如下树状结构数据呢&#xff1f; [{"customer_age"…

矩阵--旋转图像

给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 &#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&a…

嵌入式Day33---Linux软件编程---网络编程

目录 一、TCP包头 1.1.源端口 1.2.目的端口 1.3.序号 1.4.确认号 1.5.数据偏移 1.6.保留 1.7.指令信号 1.SYN 2.ACK 3.FIN 4.RST 5.PSH 6.URG 1.8.窗口 1.9.校验和 1.10.紧急指针 二、TCP的过程 2.1三次握手 2.2.传输数据 ​编辑 2.3.四次挥手 ​编辑 …

SpringBoot依赖之Spring Data Redis 一 List 类型

概念 Spring Data Redis (AccessDriver) 依赖名称: Spring Data Redis (AccessDriver)功能描述: Advanced and thread-safe Java Redis client for synchronous, asynchronous, and reactive usage. Supports Cluster, Sentinel, Pipelining, Auto-Reconnect, Codecs and muc…

[Qt][QSS][下]详细讲解

目录 1.样式属性0.前言1.盒模型(Box Model) 2.常用控件样式属性1.按钮2.复选框3.单选框4.输入框5.列表6.菜单栏7.注意 1.样式属性 0.前言 QSS中的样式属性⾮常多&#xff0c;不需要都记住&#xff0c;核⼼原则是⽤到了就去查 ⼤部分的属性和CSS是⾮常相似的 QSS中有些属性&am…

Linux CentOS手动安装Node.js(图文教程)

本章教程主要介绍如何在centos7上安装指定版本的Node.js 一、下载nodejs 前往Node.js官网&#xff0c;根据自己需要安装的版本进行下载。 官网下载地址&#xff1a;https://nodejs.org/zh-cn/download/prebuilt-binaries 本文&#xff0c;以v14.21.3版本介绍整个安装过程。 二、…