当前位置: 首页 > news >正文

vue3 响应式 API:ref() 和 reactive()

在 Vue 3 中,响应式系统是其核心特性之一,它使得数据的变化能够自动触发视图的更新。

官方文档:
响应式 API:核心
要更好地了解响应式 API,推荐阅读官方指南中的章节:
响应式基础 (with the API preference set to Composition API)
深入响应式系统

reactive()

基本概念

  • 作用:用于创建一个响应式的对象。如果对这个对象的属性进行修改,会自动触发视图的更新。
  • 可接收的数据类型:只能定义对象类型的响应式数据。使用reactive()定义基本类型会报错,要用ref
  • 语法let 响应式对象= reactive(源对象)
  • 返回值:一个Proxy的实例对象,简称:响应式对象
  • 类型
function reactive<T extends object>(target: T): UnwrapNestedRefs<T>

使用reactive()创建对象类型的响应式数据:

<template><div><p>姓名: {{ person.name }}</p><p>年龄: {{ person.age }}</p></div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';const person = reactive({name: '张三',age: 36
})
console.log(person)// 报错:类型“number”的参数不能赋给类型“object”的参数。
let count = reactive(0)</script>

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

直接修改响应式对象的属性值,会触发依赖这些属性的组件重新渲染:

// 直接修改,立即响应
person.name = '李四'
person.age = 24// 使用方法,调用方法后再响应
const changePerson = () => {person.name = '李四'person.age = 24
}

reactive()深层响应性

  • 对象的嵌套属性也具有响应式
    • 响应式转换是“深层”的:它会影响到所有嵌套的属性。一个响应式对象也将深层地解包任何 ref 属性,同时保持响应性。
<template><div><p>b: {{ obj.a.b }}</p><p>d: {{ obj.a.c.d }}</p><button @click="changeB">修改b</button><button @click="changeD">修改d</button></div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';const obj = reactive({a: {b: 10,c: {d: 20}},
});
const changeB = () => {obj.a.b++
}
const changeD = () => {obj.a.c.d++
}
</script>

在这个例子中,修改嵌套对象的属性也会触发响应式更新。
不管数据嵌套的有多深,reactive()一定会把数据变成响应式的。

  • 数组的响应式
    • 对响应式数组进行添加、删除、修改等操作都会触发依赖这个数组的组件重新渲染。
<template><div><ul><li v-for="item in personArr" :key="item.id">姓名:{{ item.name }} , 年龄:{{ item.age }} 岁</li></ul><button @click="addPerson">添加</button></div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';const personArr = reactive([{id: 1, name: '张三', age: 17 },{id: 2, name: '李四', age: 18 },{id: 3, name: '王二', age: 16 },
]);console.log(personArr); 
const addPerson = () => {personArr.push({ id: 4, name: '张麻子', age: 16 });
};</script>

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

  • 直接赋值整个响应式对象不会触发响应式更新
let person = reactive({name: '张三',age: 36,
});// 这样不会触发响应式更新
const changePerson = () => {person = {name: 'john',age: 30}
}// 使用Object.assign()等方法来更新属性
const changePerson = () => {Object.assign(person, {name: '李四',age: 24,});
}
  • 响应式对象的属性必须在创建时存在
const person = reactive({name: '王二',
});// 报错:类型“{ name: string; }”上不存在属性“age”。
person.age = 30;  

ref()

基本概念

ref()接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value

  • 作用:定义响应式的变量。
  • 可接收的数据类型:基本类型、对象类型的响应式数据。若ref接收的是对象类型,内部其实也是调用了reactive函数。
  • 语法let xxx = ref(初始值)。
  • 返回值:一个RefImpl的实例对象,简称ref对象或refref对象的value属性是响应式的。
  • 类型
function ref<T>(value: T): Ref<UnwrapRef<T>>interface Ref<T> {value: T
}

ref 对象是可更改的,也就是说可以为 .value 赋予新的值。它也是响应式的,即所有对 .value 的操作都将被追踪。

使用 ref() 创建基本类型的响应式数据

<template><div><p>count: {{ count  }}</p></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'// 在组合式 API 中,推荐使用 ref() 函数来声明响应式状态
const count = ref(0)
consoe.log(count)    // count 是一个RefImpl的实例对象
console.log('count.value:', count.value) // count.value:0count.value = 1
console.log('count.value:', count.value) // count.value:1
</script>

控制台打印:
在这里插入图片描述
注意:

  • JS中操作数据需要:xxx.value,但模板中不需要.value,直接使用{{xxx}}
  • 对于const count = ref(0)来说,count不是响应式的,count.value是响应式的。

ref()深层响应性

ref()包裹的是一个对象时,对这个对象的属性进行修改也会触发响应式更新。

<template><div><p>姓名: {{ person.name }}</p><p>年龄: {{ person.age }}</p><button @click="changePerson">修改信息</button></div>
</template>
<script setup lang="ts">
import { ref } from 'vue';const person = ref({name: '张三',age: 36
})
console.log(person)const changePerson = () => {person.name = '李四'person.age = 24
}
</script>

使用ref()定义一个对象类型的响应式数据,页面是正常展示数据的:
在这里插入图片描述
数据详细信息解析:

  • RefImpl {... }:这表示这是一个由ref函数创建的响应式对象的内部实现结构展示。
  • __v_isShallow:表示是否是浅层响应式,这里为false,说明不是浅层响应式。
  • dep:这是一个依赖收集器,用于跟踪哪些部分的代码依赖于这个响应式对象。当响应式对象的值发生变化时,会通知依赖它的部分进行更新。这里显示为一个包含一个ReactiveEffectMap,说明有一个依赖项。
  • __v_isRef:为true,表明这是一个由ref创建的响应式引用。
  • _rawValue:存储了原始的值,这里是一个包含nameage属性的对象。
  • _valuevalue:都是代理对象,通过代理可以实现对原始对象的响应式追踪。
  • [[Handler]][[Target]]:是与代理对象相关的内部属性,[[Handler]]是处理程序,用于定义对目标对象的各种操作的拦截行为,[[Target]]是被代理的原始对象。

从控制台打印的数据结构可以看出:如果将一个对象赋值给 ref,那么这个对象将通过 reactive() 转为具有深层次响应式的对象。

表面上它返回来的是一个RefImpl的实例对象,但是在这个实例对象的_valuevalue属性里,是 reactive() 的返回值:一个Proxy的实例对象。

直接调用changePerson修改信息,person没有被修改。编译器会报错:

const changePerson = () => {// 报错:类型“Ref<{ name: string; age: number; }>”上不存在属性“name”。person.name = '李四'// 报错:类型“Ref<{ name: string; age: number; }>”上不存在属性“age”。person.age = 24console.log(person)
}

ref定义的数据,如果要修改,要用.value来更改。

const changePerson = () => {console.log('修改前打印person.value:', person.value)person.value.name = '李四'person.value.age = 24console.log(person)
}

在这里插入图片描述

可以使用Vue - Official插件自动添加.value

在这里插入图片描述

在这里插入图片描述

ref()reactive()的区别

  1. 从数据类型看
    • ref()用来定义:基本类型数据对象类型数据
    • reactive()用来定义:对象类型数据
  2. 返回值类型
    • ref()返回值: 一个RefImpl的实例对象。
    • reactive()返回值:一个Proxy的实例对象,简称:响应式对象。
  3. 响应式更新方式
  • ref()通过修改.value属性来触发响应式更新。
    ref()跳过 .value属性直接修改变量的值,不会出发响应式更新。
import { ref } from 'vue';
let person = ref({name: '张三', age: 36});
const changePerson = () => {// 重新分配一个对象,触发响应式更新person.value = { name: '李四', age: 24 }// ref 跳过 .value,不会出发响应式更新person = { name: '李四', age: 24 }
}let count = ref(0)
const changeCount = () => {// 可以触发响应式更新count.value ++;// 不会触发响应式更新count = ref(10)
}
  • reactive()直接修改对象的属性即可触发响应式更新。
import { reactive } from 'vue';
let person = reactive({name: '张三', age: 36});
const changePerson = () => {person.name = '李四'   // 触发响应式更新person.age = 30        // 触发响应式更新
}
  • reactive()重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)。
import { reactive } from 'vue';
let person = reactive({name: '张三', age: 36});// 不会触发响应式更新
const changePerson = () => {// 重新分配一个对象person = { name: '李四', age: 24 }// person = reactive({name: '张三', age: 36});// 与person = reactive({ name: '李四',age: 24 });// 是完全不同的2个完全不同的person, 根本不是同一个东西person = reactive({ name: '李四', age: 24 });
}// 使用Object.assign()等方法来更新属性
const changePerson = () => {Object.assign(person, {name: '李四',age: 24,});
}
  1. 深层响应性

    • reactive()可以自动保持对象的深层响应性,即嵌套对象的属性修改也会触发响应式更新。
    • 对于ref()包裹的对象,直接修改嵌套对象的属性可能不会触发响应式更新,需要特殊处理。
  2. 使用场景

    • 若需要一个基本类型的响应式数据,必须使用ref()
    • 若需要一个响应式对象,层级不深,ref()reactive()都可以。
    • 若需要一个响应式对象,且层级较深,推荐使用reactive()

相关文章:

vue3 响应式 API:ref() 和 reactive()

在 Vue 3 中&#xff0c;响应式系统是其核心特性之一&#xff0c;它使得数据的变化能够自动触发视图的更新。 官方文档&#xff1a; 响应式 API&#xff1a;核心 要更好地了解响应式 API&#xff0c;推荐阅读官方指南中的章节&#xff1a; 响应式基础 (with the API preference…...

英智金融行业AI Agent,在金融领域全场景下的业务创新与应用实践

随着全球经济的数字化转型&#xff0c;金融行业也在迅速演变。传统的金融服务已经无法完全满足现代客户对快速、个性化和高效服务的需求。与此同时&#xff0c;市场竞争的加剧、监管环境的变化以及客户期望的提升&#xff0c;促使金融机构不断寻求新的技术来优化运营效率、提升…...

hyper-v安装window10操作系统

Hyper-V是微软的一款虚拟化产品&#xff0c;是微软第一个采用类似Vmware ESXi和Citrix Xen的基于hypervisor的技术。 目标&#xff1a;在window10的物理机上基于hyper-v运行虚拟window10。 准备条件 准备好window10操作系统&#xff0c;iso、wim、esd等都行&#xff0c;我这…...

华三(H3C)UIS3030 Uni-R4900服务器硬件监控指标解读

随着企业信息化建设的不断深入&#xff0c;服务器作为IT架构的核心组成部分&#xff0c;其稳定性和性能直接影响到业务的连续性和用户体验。为了保障服务器的稳定运行&#xff0c;监控易作为一款专业的监控软件&#xff0c;为华三&#xff08;H3C&#xff09;UIS3030和Uni-R490…...

opencv 控制鼠标键盘实现功能setMouseCallback

鼠标事件类型 OpenCV 支持多种鼠标事件类型&#xff0c;常见的包括&#xff1a; cv2.EVENT_LBUTTONDOWN&#xff1a;左键按下 cv2.EVENT_RBUTTONDOWN&#xff1a;右键按下 cv2.EVENT_MBUTTONDOWN&#xff1a;中键按下 cv2.EVENT_LBUTTONUP&#xff1a;左键释放 cv2.EVENT_RBUTT…...

【傅里叶分析】复数基础知识

【傅里叶分析】复数基础知识 复数复数的几何意义与点的对应与向量的对应 复数与极坐标辐角与辐角主值三角函数 参考文献 本文参考了网上的其他文章&#xff0c;已在文末参考文献中列出&#xff1b;如有侵权&#xff0c;请联系我删除。 复变函数是傅里叶分析的基础&#xff0c;而…...

从【人工智能】到【计算机视觉】,【深度学习】引领的未来科技创新与变革

前几天偶然发现了一个超棒的人工智能学习网站&#xff0c;内容通俗易懂&#xff0c;讲解风趣幽默&#xff0c;简直让人欲罢不能。忍不住分享给大家&#xff0c;点击这里立刻跳转&#xff0c;开启你的AI学习之旅吧&#xff01; 前言 – 人工智能教程https://www.captainbed.cn/l…...

基于YOLOv10深度学习的草莓成熟度检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、人工智能

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…...

log4j日志配置%X{TransId}

log4j日志配置文件中的%X{TransId}是怎么动态获取值的 在Log4j中&#xff0c;%X{TransId} 是用来从MDC&#xff08;Mapped Diagnostic Context&#xff09;中获取值的占位符。MDC 是 Log4j 提供的一种机制&#xff0c;用于在同一个线程的不同日志记录中传递上下文信息。通过 M…...

PHP模拟高并发异步请求测试+redis的setnx处理并发和防止死锁处理

/** PHP并发异步请求测试* /test/curlMulti*/public function curlMultiAction(){$urls ["http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhos…...

访问网站出现“此站点不安全”如何解决

在网络浏览中&#xff0c;我们经常会遇到浏览器地址栏出现“此站点不安全”的警告。这通常意味着网站没有使用SSL&#xff08;安全套接层&#xff09;加密来保护用户数据的安全。那么&#xff0c;如何通过获得并安装SSL证书来消除这一警告&#xff0c;确保网站的安全可靠呢&…...

同一台电脑同时连接使用Gitee(码云)和Github

1、添加对应的密钥 ssh-keygen -t rsa -C "your_emailexample.com" -f ~/.ssh/github_id-rsa //生成github秘钥 ssh-keygen -t rsa -C "your_emailexample.com" -f ~/.ssh/gitee_id-rsa //生成码云秘钥 2、在 ~/.ssh 文件里会生成对应的文件 文件夹里会…...

GORM 插入和批量插入操作介绍

GORM 是一个功能强大的 Go 语言 ORM 库&#xff0c;它提供了简单易用的 API 来执行数据库操作。本文将介绍如何使用 GORM 进行单条记录插入和批量插入操作。 单条记录插入 在 GORM 中&#xff0c;插入一条记录非常简单。首先&#xff0c;你需要定义一个模型&#xff0c;该模型…...

企业CAD图纸加密软件推荐!2024年好用的10款CAD图纸加密软件排行

在现代企业中&#xff0c;CAD图纸作为重要的设计和工程数据&#xff0c;其安全性和保密性至关重要。为了防止图纸被非法获取、篡改或滥用&#xff0c;选择一款高效的CAD图纸加密软件显得尤为重要。本文将为您推荐2024年市场上十款好用的CAD图纸加密软件&#xff0c;帮助企业保护…...

智能电梯标志新时代:墨水屏电子标签引领变革

电梯安全墨水屏标签的智能设备悄然出现在各大写字楼和住宅区的电梯中&#xff0c;引发了广泛关注。这款设备替代了传统的纸质电梯标志&#xff0c;通过手机蓝牙标签APP直接进行编辑刷新内容&#xff0c;并具备Type-C接口充电功能。 本文将深入探讨这一创新技术的应用前景及其对…...

使用nvm下载nodejs版本报错

这里写自定义目录标题 使用nvm下载nodejs版本报错&#xff1a;Error retrieving "http://npm.taobao.org/mirrors/node/latest/SHASUMS256.txt": HTTP Status 404问题原因解决办法 使用nvm下载nodejs版本报错&#xff1a;Error retrieving “http://npm.taobao.org/m…...

深入理解CSS的:valid和:invalid伪类:增强表单验证的艺术

在现代网页设计中&#xff0c;用户输入验证是一个重要的环节&#xff0c;它不仅关乎用户体验&#xff0c;也是数据准确性和安全性的保障。CSS3引入了两个强大的伪类选择器&#xff1a;:valid和:invalid&#xff0c;它们允许开发者通过CSS来增强表单输入的验证过程&#xff0c;而…...

稚晖君发布5款全能人形机器人,开源创新,全能应用

8月18日&#xff0c;智元机器人举行“智元远征 商用启航” 2024年度新品发布会&#xff0c;智元联合创始人彭志辉主持并发布了“远征”与“灵犀”两大系列共五款商用人形机器人新品——远征A2、远征A2-W、远征A2-Max、灵犀X1及灵犀X1-W&#xff0c;并展示了在机器人动力、感知、…...

【总结】冲击偶的概念与性质

冲击偶的概念与性质...

Hbase图形化界面

分享一个好用的hbase图形化界面 安装包&#xff1a;链接: https://pan.baidu.com/s/11Y2cDlme-P2xe--pYqy6MQ?pwdguag 提取码: guag 1、上传项目到linux 2、修改数据库配置信息 application-druid.yml 修改url、username、password为数据库连接信息 3、创建数据库(注意字符集…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

CppCon 2015 学习:Time Programming Fundamentals

Civil Time 公历时间 特点&#xff1a; 共 6 个字段&#xff1a; Year&#xff08;年&#xff09;Month&#xff08;月&#xff09;Day&#xff08;日&#xff09;Hour&#xff08;小时&#xff09;Minute&#xff08;分钟&#xff09;Second&#xff08;秒&#xff09; 表示…...

raid存储技术

1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划&#xff0c;涵盖存储系统的布局、数据存储策略等&#xff0c;它明确数据如何存储、管理与访问&#xff0c;为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...

vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能

vxe-table vue 表格复选框多选数据&#xff0c;实现快捷键 Shift 批量选择功能 查看官网&#xff1a;https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...