vue3-ref 和 reactive
文章目录
- vue3 中 ref 和 reactive
- reactive 与 ref 不同之处
- ref 处理复杂类型
- ref在dom中的应用
vue3 中 ref 和 reactive
- ref原理
- 基本原理
ref是Vue 3中用于创建响应式数据的一个函数。它的基本原理是通过Object.defineProperty()(在JavaScript的规范中用于定义对象属性的方法)或者Proxy(ES6新特性,用于创建对象的代理)来实现数据的响应式。当数据被修改时,它会触发更新相关的副作用函数(例如更新DOM等操作)。- 当使用
ref创建一个响应式数据时,它实际上返回一个包含value属性的对象。例如,const count = ref(0),这里的count是一个对象,访问和修改数据需要通过count.value。
- 底层实现细节(简单示例)
- 以下是一个简单的模拟
ref实现的代码(简化版,实际Vue 3代码更复杂):
- 以下是一个简单的模拟
- 基本原理
function ref(raw) {const r = {get value() {track(r, 'value');return raw;},set value(newVal) {if (newVal!== raw) {raw = newVal;trigger(r, 'value');}}};return r;
}
- 这里的
track函数用于收集依赖(记录哪些函数依赖了这个ref数据),trigger函数用于触发更新(当数据改变时,通知依赖的函数重新执行)。
- reactive原理
- 基本原理
reactive是基于Proxy对象来实现响应式的。Proxy可以拦截对目标对象的各种操作,如读取属性、设置属性、删除属性等。当这些操作发生时,reactive可以触发相应的更新逻辑。- 例如,
const state = reactive({ count: 0 }),对state.count的读取和修改都会被Proxy拦截,从而实现响应式。
- 底层实现细节(简单示例)
- 以下是一个简单的模拟
reactive实现的代码片段(简化版):
- 以下是一个简单的模拟
- 基本原理
function reactive(target) {return new Proxy(target, {get(target, key, receiver) {track(target, key);return Reflect.get(target, key, receiver);},set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);trigger(target, key);return result;}});
}
- 同样,这里的
track和trigger函数用于收集依赖和触发更新,和ref的原理类似,但是reactive是针对整个对象的属性进行拦截。
-
ref和reactive的应用场景
- ref应用场景
- 基本数据类型:当处理基本数据类型(如
number、string、boolean)的响应式数据时,通常使用ref。例如,一个计数器const count = ref(0),这里count是一个ref对象,通过count.value来访问和修改计数值。 - 在组合式API中传递单个数据:如果在组合式API函数之间传递一个简单的响应式数据,
ref是一个很好的选择。比如一个函数返回一个ref数据,另一个函数可以接收并使用这个ref。
- 基本数据类型:当处理基本数据类型(如
- reactive应用场景
- 复杂对象类型:对于复杂的对象(如包含多个属性的对象或数组),使用
reactive更为合适。例如,const state = reactive({ name: 'John', age: 30, hobbies: ['reading', 'coding']}),对state对象中的任何属性的访问和修改都会是响应式的。 - 多个相关数据的管理:当需要管理一组相关的数据并且希望它们作为一个整体进行响应式处理时,
reactive是首选。比如一个表单数据对象,包含表单的各个字段值,使用reactive可以方便地处理整个表单数据的更新和响应。
- 复杂对象类型:对于复杂的对象(如包含多个属性的对象或数组),使用
- ref应用场景
-
应用要求/依据
- 响应式数据的修改原则
- 对于
ref,必须通过.value属性来修改数据才能触发响应式更新。例如,count.value++会触发更新,而直接count = new_value(这里count是ref)不会触发响应式更新。 - 对于
reactive,直接修改对象的属性就可以触发响应式更新。如state.name = 'Jane'(这里state是reactive对象)会触发更新。
- 对于
- 模板中的使用差异
- 在Vue 3的模板中,
ref的数据可以直接在模板中使用,不需要额外的.value语法。例如,<div>{{ count }}</div>(这里count是ref)是可以正常工作的,Vue会自动处理value属性的访问。而对于reactive对象,直接通过属性访问即可,如<div>{{ state.name }}</div>(这里state是reactive对象)。
- 在Vue 3的模板中,
- 响应式数据的修改原则
reactive 与 ref 不同之处
- 数据类型处理方式不同
- ref
- 主要用于包装基本数据类型(如
number、string、boolean),使其具有响应式特性。例如const count = ref(0),count是一个对象,它有一个value属性来存储实际的数据。在JavaScript代码中,必须通过count.value来访问和修改这个数据。
- 主要用于包装基本数据类型(如
- reactive
- 用于处理复杂的对象类型(如对象字面量或数组),它会递归地将对象的所有属性转换为响应式。例如
const state = reactive({ count: 0, message: 'Hello'}),state本身就是响应式对象,对state.count和state.message等属性的访问和修改都是响应式的,不需要像ref那样通过特定的value属性来操作。
- 用于处理复杂的对象类型(如对象字面量或数组),它会递归地将对象的所有属性转换为响应式。例如
- ref
- 在模板中的使用差异
- ref
- 在Vue 3模板中使用
ref时,不需要显式地访问value属性。Vue会自动进行解包,例如,如果count是一个ref,在模板中可以直接写成<div>{{ count }}</div>,它会正确地渲染count.value的值。
- 在Vue 3模板中使用
- reactive
- 对于
reactive对象,在模板中直接通过属性访问来使用。如const state = reactive({ name: 'John'}),在模板中可以写成<div>{{ state.name }}</div>来显示name属性的值。
- 对于
- ref
- 响应式转换的深度不同
- ref
- 只对它包装的那个数据本身进行响应式处理。如果
ref包装了一个对象,它不会自动将对象内部的属性也转换为响应式,仍然需要通过value属性来访问对象,并且如果要使对象内部属性具有响应式,可能还需要进一步的处理(如使用reactive来处理这个对象)。
- 只对它包装的那个数据本身进行响应式处理。如果
- reactive
- 是深度响应式的。当使用
reactive处理一个对象时,它不仅会使对象本身的属性具有响应式,还会递归地将对象内部嵌套的对象和数组的属性也转换为响应式。例如,如果有一个对象const user = reactive({ name: 'Alice', address: { city: 'New York', street: '123 Main St' }}),那么user.address.city的访问和修改也是响应式的。
- 是深度响应式的。当使用
- ref
- 创建和使用的语法及场景差异
- ref
- 创建语法简单直接,适用于单个数据值的响应式处理,特别是基本数据类型。在组合式API中,当需要从一个函数返回一个响应式数据,并且这个数据是基本类型或者只需要简单的包装时,
ref是很好的选择。
- 创建语法简单直接,适用于单个数据值的响应式处理,特别是基本数据类型。在组合式API中,当需要从一个函数返回一个响应式数据,并且这个数据是基本类型或者只需要简单的包装时,
- reactive
- 创建时需要传入一个对象,更适合处理复杂的、有多个相关属性的数据结构,如应用程序中的状态对象。当有一组相关的数据需要作为一个整体进行响应式管理时,如表单数据、应用的全局状态等,
reactive是更合适的方式。
- 创建时需要传入一个对象,更适合处理复杂的、有多个相关属性的数据结构,如应用程序中的状态对象。当有一组相关的数据需要作为一个整体进行响应式管理时,如表单数据、应用的全局状态等,
- ref
ref 处理复杂类型
-
ref处理复杂类型
- 从功能上来说,
ref可以用来包装复杂的数据类型,如对象或数组。例如,可以使用ref创建一个包含多个属性的对象,const myObject = ref({name: 'John', age: 30})。
- 从功能上来说,
-
限制
- 访问方式的限制
- 在JavaScript代码中,必须通过
value属性来访问和修改包装后的复杂对象。例如,要访问上述myObject中的name属性,需要使用myObject.value.name。这与reactive不同,reactive可以直接通过属性访问(如const myReactiveObject = reactive({name: 'Alice'}); myReactiveObject.name)。这种访问方式的差异可能会导致代码不够简洁直观,尤其是在处理多层嵌套的复杂对象时。
- 在JavaScript代码中,必须通过
- 响应式转换深度的限制
ref本身不会对包装的复杂对象内部进行深度的响应式转换。例如,如果有一个ref包装的对象const user = ref({name: 'Bob', address: {city: 'New York'}}),修改user.value.address.city不会自动触发响应式更新,除非address这个对象本身也经过了响应式处理(如使用reactive来处理address对象)。而reactive会自动对对象内部进行深度响应式处理。
- 在模板中的限制(部分)
- 在Vue 3的模板中,
ref包装的复杂对象在某些情况下可能会引起混淆。虽然Vue会自动展开ref的值,但对于复杂对象的属性访问,有时候可能需要注意绑定的语法。例如,如果要在模板中使用myObject中的name属性,写成{{myObject.name}}是不行的,需要写成{{myObject.value.name}},不过Vue在模板渲染时会自动处理ref的value属性,使得在大多数简单情况下可以像使用普通数据一样使用ref包装的数据。但在复杂的模板绑定场景下,还是要注意正确的语法。
- 在Vue 3的模板中,
- 访问方式的限制
ref在dom中的应用
- 应用实例
- 基本计数器示例
- 在Vue 3组件中,可以使用
ref来获取DOM元素,并对其进行操作。以下是一个简单的计数器组件,当点击按钮时,计数器的值会增加,并且会更新DOM中的显示内容。
- 在Vue 3组件中,可以使用
- 基本计数器示例
<template><div><p ref="counterDisplay">{{ count }}</p><button @click="increment">Increment</button></div>
</template><script>
import { ref, defineComponent } from 'vue';
export default defineComponent({setup() {const count = ref(0);const counterDisplay = ref(null);const increment = () => {count.value++;if (counterDisplay.value) {// 直接操作DOM元素的文本内容counterDisplay.value.textContent = count.value;}};return {count,counterDisplay,increment};}
});
</script>
- 表单验证示例
- 假设有一个简单的表单,通过
ref获取表单元素,用于检查表单是否有效。
- 假设有一个简单的表单,通过
<template><form ref="myForm"><input type="text" v-model="username"><button @click="checkFormValidity">Check Validity</button></form>
</template><script>
import { ref, defineComponent } from 'vue';
export default defineComponent({setup() {const username = ref('');const myForm = ref(null);const checkFormValidity = () => {if (myForm.value) {const isFormValid = myForm.value.checkValidity();console.log('Form is valid:', isFormValid);}};return {username,myForm,checkFormValidity};}
});
</script>
- 原理
- 挂载阶段(mounted)
- 当组件被挂载时,
ref对应的DOM元素会被赋值。在Vue 3中,组件的setup函数执行过程中,ref初始化为null。然后,在组件的生命周期钩子(如onMounted)或者在模板渲染完成后(实际上是Vue内部的渲染机制),ref会被正确地赋值为对应的DOM元素。这是因为Vue在渲染过程中会遍历模板,识别出带有ref属性的DOM元素,并将其与对应的ref变量关联起来。
- 当组件被挂载时,
- 更新阶段(update)
- 当组件的状态发生变化(如
count的值改变)并导致DOM需要更新时,Vue会重新渲染模板。在这个过程中,ref变量仍然保持对相应DOM元素的引用。如果在setup函数中有对ref变量所引用的DOM元素进行操作的代码(如修改textContent),这些操作会在DOM更新完成后或者在适当的时机(由Vue的响应式更新机制决定)执行。
- 当组件的状态发生变化(如
- 响应式原理关联
ref用于操作DOM元素也与Vue的响应式原理相关。当一个ref变量(如count)的值发生变化时,Vue会触发组件的重新渲染。在重新渲染过程中,其他与ref相关的操作(如操作counterDisplay所引用的DOM元素)可以利用这个更新时机来实现对DOM的动态操作。同时,ref本身的更新机制(通过value属性访问和修改)也保证了操作的一致性和可追踪性,使得在组件的整个生命周期内能够正确地对DOM进行操作。
- 挂载阶段(mounted)
相关文章:
vue3-ref 和 reactive
文章目录 vue3 中 ref 和 reactivereactive 与 ref 不同之处ref 处理复杂类型ref在dom中的应用 vue3 中 ref 和 reactive ref原理 基本原理 ref是Vue 3中用于创建响应式数据的一个函数。它的基本原理是通过Object.defineProperty()(在JavaScript的规范中用于定义对…...
Apache Calcite - 查询优化之自定义优化规则
RelOptRule简介 为了自定义优化规则,我们需要继承RelOptRule类。org.apache.calcite.plan.RelOptRule 是 Apache Calcite 中的一个抽象类,用于定义优化规则。优化规则是用于匹配查询计划中的特定模式,并将其转换为更优化的形式的逻辑。通过继…...
大型语言模型(LLM)的小型化研究进展
2024年,大型语言模型(LLM)的小型化研究取得了显著进展,主要采用以下几种方法实现: 模型融合:通过将多个模型或检查点合并为一个单一模型,减少资源消耗并提升整体性能。例如,《WARM: …...
MiniWord
1.nuget 下载配置 2.引用 3. var value = new Dictionary<string, object>() { ["nianfen"] = nianfen, ["yuefen"] = yuefen, ["yuefenjian1"] = (int.Par…...
Netty 常见组件介绍
Netty 常见组件介绍 上篇文章Netty入门程序echo 基本包含了Netty常见的组件,本文分别介绍各个组件 Bootstrap or ServerBootstrapEventLoopEventLoopGroupChannelPipelineChannelFuture or ChannelFutureChannelInitializerChannelHandler Bootstrap vs ServerBo…...
高频电子线路---倍频器与振荡器
目录 倍频电路原理 丙类倍频器原理电路 问题: 提升滤波方法: 导通角 振荡器 振荡器基本工作原理 首先是怎么维持 那么如何振荡呢? 思考题: 组成要素 振荡器的起振条件 平衡条件 要点提示 稳定条件 振幅平衡 硬激励起振时: 稳定条件 相位平衡 倍频电路原理 简单原理 : …...
删除 git submodule
直接运行下面命令即可: git rm <path-to-submodule>然后提交修改即可。 但是,还有一个小问题:上面命令只是将 submodule 的代码目录删除了。 以下痕迹还存在你的仓库中: .gitmodule 中关于该 submodule 的信息.git 目录…...
el-table 多选默认选中(根据返回的id给数据加默认选中状态)
前言 el-table是我们最常用的展示数据的方式,但是有时候需要用到多选来选择数据,新增数据的时候还好,选中状态都是正常的,但是修改就遇到问题,需要对这个已经选择过的数据加上默认的选中状态,本次就是解决…...
境外网站翻译之自由职业
Polls Do you use AI tools (e.g ChatGPT, Midjourney, Github Copilot) as part of your work? 你在工作中会使用人工智能工具(如 ChatGPT、Midjourney、Github Copilot)吗? Yes, as an assistant 是的,作为一种辅助工具。 Y…...
批量图片转PDF文件的多种方法详解
要将批量图片转换为PDF文件,可以使用多种方法,包括使用在线工具、桌面应用程序或编程语言。以下是几种常见的方法: 方法一:使用在线工具 选择工具:搜索“图片转PDF”在线工具,如 Smallpdf、ILovePDF 等。…...
Web服务器(理论)
目录 Web服务器www简介常见Web服务程序介绍:服务器主机主要数据浏览器 网址及HTTP简介URLhttp请求方法:2.3 HTTP协议请求的工作流程: www服务器的类型静态网站动态网站 快速安装Apache安装准备工作httpd所需目录主配置文件 nignx安装1、安装2、准备工作 …...
js:()=>(,);()的作用:明确表达式的边界。
()>{表达式1;表达式2;表达式3;... return 结果} 等同于 ()>(表达式1,表达式2,表达式3,... 结果) 例子: const strarr [a, b, c];const result strarr.reduce((acc, curr) > {(acc[curr] 1);console.lo…...
RSI 5G通信技术中用于标识小区的特定参数
RSI是指在5G通信技术中用于标识小区的特定参数,全称为Radio Subframe Indicator(无线子帧指示符)。在原文的上下文中,RSI被用来确保相邻小区间有足够的间隔,避免由于RSI冲突导致用户设备(UE)随机…...
JavaScript中的闭包、递归问题
一、函数定义和调用 1.函数的定义方式 方式一 函数声明方式 function 关键字(命名函数) function fn(){}方式二 函数表达式(匿名函数) var fn function(){}方式三 new Function() var f new Function(a,b,console.log(a b););//语法 var fn new Fu…...
【青牛科技】GC4938替代A4938/Allegro在水泵、筋膜枪、吸尘器和电动工具中的应用
随着技术的不断进步,电机驱动控制器在各类电动设备中的应用越来越广泛。GC4938作为一种新型的电机驱动控制器,逐渐被视为A4938/Allegro的替代品。在这篇文章中,我们将探讨GC4938在水泵、筋膜枪、吸尘器和电动工具等设备中的应用优势和特点。 …...
基于yolov5的输电线,电缆检测系统,支持图像检测,视频检测和实时摄像检测功能(pytorch框架,python源码)
更多目标检测和图像分类识别项目可看我主页其他文章 功能演示: yolov5,输电线(线缆)检测系统,系统既支持图像检测,也支持视频和摄像实时检测【pytorch框架】_哔哩哔哩_bilibili (一)简介 基于yolov5的输…...
uniapp下载文件的方案,包括H5,App方案解决办法
1. 在uniapp需要下载文件,但是显示情况是不能下载。所以只能使用该办法来进行下载。 2. 这有一个注意点是:如果你做的是H5的方案,那么我已经替你踩好坑了,UC浏览器是不支持blob类型的下载,以及创建a标签的方案来进行下…...
c++ 贪心算法
概念 贪心算法是一种在每一步选择中都选择当前最优解的算法策略。这种方法适用于某些特定问题,可以通过局部最优选择构建全局最优解。 特点 局部最优选择:每一步选择都选择当前看起来最优的解。无后效性:当前选择不会影响未来选择的可能性…...
15分钟学 Go 第 35 天:Go的性能调优 (7000字详细教程)
第35天:Go的性能调优 目标:理解Go语言中基本的性能优化,学习如何分析和提高Go程序的执行效率。 一、性能调优概述 性能调优是软件开发中的一个重要环节,它可以确保程序在资源有限的环境下高效运行。Go语言天生具备高效的性能表现…...
6、显卡品牌分类介绍:技嘉 - 计算机硬件品牌系列文章
技嘉科技是一家以主板、显卡在业界缔造无以撼动的地位的科技公司,其核心理念是「技术创新、质量稳定」的高标准。技嘉专注于关键技术研发,其经营范围涵盖家用、商用、电竞等多元科技领域。通过应用突破性的专利技术,技…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
