在 Vue3 的 Composition API 中,ref() 是最基础也是最常用的响应式数据声明方式之一。它为开发者提供了一种简单而强大的方式来管理组件状态。本文将深入探讨 ref() 的工作原理、使用场景以及最佳实践。

1. 什么是 ref()?

ref() 是 Vue3 提供的一个函数,用于创建一个响应式的引用对象。它可以包装任何类型的值,使其变为响应式数据。

import { ref } from 'vue'const count = ref(0)

2. ref() 的核心特性

2.1 响应式包装

ref() 接受一个内部值并返回一个响应式的、可变的 ref 对象,该对象只有一个 .value 属性指向内部值。

const num = ref(10)
console.log(num.value) // 10num.value = 20
console.log(num.value) // 20

2.2 类型保留

ref() 会保留原始值的类型信息,TypeScript 用户可以获得完整的类型推断。

const message = ref('Hello') // Ref<string>
const age = ref(25) // Ref<number>
const user = ref({ name: 'Alice' }) // Ref<{ name: string }>

2.3 模板自动解包

在模板中使用 ref 时,不需要通过 .value 访问,Vue 会自动解包。

<template><div>{{ count }}</div><!-- 不需要写成 count.value -->
</template>

3. ref() 的工作原理

3.1 底层实现

ref() 本质上是对 reactive() 的封装,它创建了一个包含 value 属性的响应式对象:

function ref(value) {return reactive({ value })
}

3.2 为什么需要 ref()?

你可能会有疑问:既然有 reactive(),为什么还需要 ref()?主要原因有:

  1. 原始值包装:JavaScript 原始值(string, number, boolean 等)不是对象,无法用 reactive() 直接包装。
  2. 一致性:在组合函数中返回响应式值时,使用 ref() 可以保持一致性。
  3. 性能考虑:对于简单值,ref()reactive() 更轻量。

4. ref() 的使用场景

4.1 基本类型数据

const name = ref('Alice')
const age = ref(25)
const isActive = ref(true)

4.2 DOM 元素引用

<template><input ref="inputRef" />
</template><script setup>
import { ref, onMounted } from 'vue'const inputRef = ref(null)onMounted(() => {inputRef.value.focus()
})
</script>

4.3 组合函数返回值

// useCounter.js
import { ref } from 'vue'export function useCounter(initialValue = 0) {const count = ref(initialValue)function increment() {count.value++}return {count,increment}
}

5. ref() 的高级用法

5.1 解构 ref 对象

const user = ref({name: 'Alice',age: 25
})// 解构会失去响应性
const { name, age } = user // ❌ 错误方式// 正确方式:使用 toRefs
import { toRefs } from 'vue'
const { name, age } = toRefs(user.value) // ✅

5.2 ref() 与 reactive() 结合

const state = reactive({count: ref(0), // 自动解包user: ref({ name: 'Alice' })
})console.log(state.count) // 0,不需要 .value

5.3 自定义 ref

Vue 提供了 customRef() 用于创建自定义的 ref 实现:

import { customRef } from 'vue'function debouncedRef(value, delay = 200) {let timeoutreturn customRef((track, trigger) => {return {get() {track()return value},set(newValue) {clearTimeout(timeout)timeout = setTimeout(() => {value = newValuetrigger()}, delay)}}})
}const text = debouncedRef('hello')

6. ref() 的注意事项

  1. .value 访问:在 JavaScript 中必须通过 .value 访问 ref 的值,但在模板中会自动解包。
  2. 嵌套 ref:避免不必要的嵌套 ref,如 ref(ref(0))
  3. 数组和对象:对于复杂数据结构,reactive() 可能更合适。
  4. 解构问题:直接解构 ref 对象会失去响应性,使用 toRefs 解决。

7. ref() vs reactive()

特性ref()reactive()
创建方式ref(value)reactive(object)
访问方式需要 .value (JS中)直接访问
适用类型任意类型对象/数组
模板使用自动解包直接使用
解构需要使用 toRefs需要使用 toRefs

8. 性能考虑

  • ref() 对于简单值比 reactive() 更轻量
  • 避免在大型数组或复杂对象上使用多个 ref(),考虑使用 reactive()
  • 在组合函数中优先返回 ref() 以保持一致性

9. 最佳实践

  1. 命名约定:为 ref 对象添加 Ref 后缀,如 inputRef,提高代码可读性。
  2. 类型安全:为 ref 提供明确的类型注解(TypeScript)。
  3. 适度使用:简单数据用 ref(),复杂对象用 reactive()
  4. 组合函数:在可组合函数中始终返回 ref() 以保持一致性。

10. 结语

ref() 作为 Vue3 响应式系统的基石之一,提供了简单而强大的状态管理能力。理解其工作原理和适用场景,能够帮助开发者编写更高效、更可维护的 Vue 代码。无论是简单的计数器还是复杂的业务逻辑,ref() 都能胜任,是 Vue3 开发中不可或缺的工具。

希望本文能帮助你更好地理解和运用 ref(),在你的 Vue 项目中发挥它的最大价值!

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML常用标签汇总(精简版)

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>简单标记</title> </head><body>&…

【.net core】支持通过属性名称索引的泛型包装类

类/// <summary> /// 支持通过属性名称索引的泛型包装类 /// </summary> public class PropertyIndexer<T> : IEnumerable<T> {private T[] _items;private T _instance;private PropertyInfo[] _properties;private bool _caseSensitive;public Prope…

【机器学习|学习笔记】详解支持向量机(Support Vector Machine,SVM)为何要引入核函数?为何对缺失数据敏感?

【机器学习|学习笔记】详解支持向量机(Support Vector Machine,SVM)为何要引入核函数?为何对缺失数据敏感? 【机器学习|学习笔记】详解支持向量机(Support Vector Machine,SVM)为何要引入核函数?为何对缺失数据敏感? 文章目录 【机器学习|学习笔记】详解支持向量机(…

Bicep入门篇

前言 Azure Bicep 是 ARM 模板的最新版本,旨在解决开发人员在将资源部署到 Azure 时遇到的一些问题。它是一款开源工具,实际上是一种领域特定语言 (DSL),它提供了一种声明式编写基础架构的方法,该基础架构描述了虚拟机、Web 应用和网络接口等云资源的拓扑结构。它还鼓励在…

命名实体识别15年研究全景:从规则到机器学习的演进(1991-2006)

本文精读NRC Canada与NYU联合发表的经典综述《A survey of named entity recognition and classification》&#xff0c;解析NERC技术演进脉络与核心方法论 一、为什么命名实体识别&#xff08;NER&#xff09;如此重要&#xff1f; 命名实体识别&#xff08;Named Entity Rec…

eNSP综合实验(DNCP、NAT、TELET、HTTP、DNS)

1搭建实验拓扑2实验目的学习掌握eNSP中的命令3实验步骤3.1配置连接PC和客户端的交换机(仅以右侧为例)[Huawei]vlan batch 10 20 #创建vlan Info: This operation may take a few seconds. Please wait for a moment...done. [Huawei]un in en [Huawei]interface e0/0/2 [Huawei…

无人系统与安防监控中的超低延迟直播技术应用:基于大牛直播SDK的实战分享

技术背景 在 无人机、机器人 以及 智能安防 等高要求行业&#xff0c;高清视频的超低延迟传输 正在成为影响系统性能与业务决策的重要因素。无论是工业生产线的远程巡检、突发事件的应急响应&#xff0c;还是高风险环境下的智能监控与远程控制&#xff0c;视频链路的传输延迟都…

go语言学习之包

概念&#xff1a;在Go 语言中&#xff0c;包由一个或多个保存在同一目录的源码文件组成&#xff0c;包名宇目录名无关&#xff0c;但是通常大家习惯包名和目录名保持一致&#xff0c;同一目录的源码文件必须使用相同的包名。包的用途类似于其他语言的命名空间&#xff0c;可以限…

pytorch学习笔记(五)-- 计算机视觉的迁移学习

系列文章目录 pytorch学习笔记&#xff08;一&#xff09;-- pytorch深度学习框架基本知识了解 pytorch学习笔记&#xff08;二&#xff09;-- pytorch模型开发步骤详解 pytorch学习笔记&#xff08;三&#xff09;-- TensorBoard的介绍 pytorch学习笔记&#xff08;四&…

数字IC后端培训教程之数字后端项目典型项目案例解析

数字IC后端低功耗设计实现案例分享(3个power domain&#xff0c;2个voltage domain) Q1: 电路如下图&#xff0c;clk是一个很慢的时钟test_clk&#xff08;属于DFT的)&#xff0c;DFF1与and 形成一个clock gating check。跑pr 发现&#xff0c;时钟树综合CTS阶段&#xff08;C…

2025 Data Whale x PyTorch 安装学习笔记(Windows 版)

一、Anaconda 的安装与基本操作 1. 安装 Anaconda/miniconda 官方链接&#xff1a;Anaconda | Individual Edition 根据系统版本选择合适的安装包下载并安装。 2. 检验安装 打开 “开始” 菜单&#xff0c;找到 “Anaconda Prompt”&#xff08;一般在 Anaconda3 文件夹…

mac OS上docker安装zookeeper

拉取镜像&#xff1a;$ docker pull zookeeper:3.5.7 3.5.7: Pulling from library/zookeeper 3.5.7: Pulling from library/zookeeper 3.5.7: Pulling from library/zookeeper no matching manifest for linux/arm64/v8 in the manifest list entries报错&#xff1a;由于时M3…

设备通过4G网卡接入EasyCVR视频融合平台,出现无法播放的问题排查和解决

EasyCVR视频融合平台作为支持多协议接入、多设备集中管理的综合性视频解决方案&#xff0c;可实现各类终端设备的视频流汇聚与实时播放。近期收到用户反馈&#xff0c;在EasyCVR平台接入设备后出现视频流无法播放的情况。为帮助更多用户快速排查同类问题&#xff0c;现将具体处…

板凳-------Mysql cookbook学习 (十二--------3)

第二章 抽象数据类型和python类 2.5类定义实例&#xff1a; 学校人事管理系统中的类 import datetimeclass PersonValueError(ValueError):"""自定义异常类"""passclass PersonTypeError(TypeError):"""自定义异常类""…

css flex 布局中 flex-direction为column,如何让子元素的宽度根据内容自动变化

在 display: flex 且 flex-direction: column 的布局中&#xff0c;默认情况下子元素会占满容器的宽度。要让子元素的宽度根据内容自适应&#xff0c;而不是自动拉伸填满父容器&#xff0c;你可以这样处理&#xff1a;✅ 解决方案一&#xff1a;设置子元素 align-self: start 或…

性能优化实践:Modbus 在高并发场景下的吞吐量提升(二)

四、Modbus 吞吐量提升实战策略4.1 优化网络配置选择合适的网络硬件是提升 Modbus 通信性能的基础。在工业现场&#xff0c;应优先选用高性能的工业级交换机和路由器。工业级交换机具备更好的抗干扰能力和稳定性&#xff0c;其背板带宽和包转发率更高&#xff0c;能够满足高并发…

上传ipa到appstore的几种工具

无论是用原生开发也好&#xff0c;使用uniapp或flutter开发也好&#xff0c;最好打包好的APP是需要上架appstore的。而在app store connect上架的时候&#xff0c;需要上传ipa文件到app store的构建版本上。因此&#xff0c;需要上传工具。下面分析下几种上传工具的优缺点&…

数控调压BUCK电路 —— 基于TPS56637(TI)

0 前言 本文基于 TI 的 TPS56637 实现一个支持调压的 BUCK 电路&#xff0c;包含从零开始详细的 原理解析、原理图、PCB 及 实测数据 本文属于《DIY迷你数控电源》系列&#xff0c;本系列我们一起实现一个简单的迷你数控电源 我是 LNY&#xff0c;一个在对嵌入式的所有都感兴…

prometheus UI 和node_exporter节点图形化Grafana

prometheus UI 和node_exporter节点图形化Grafana 先简单的安装一下 进行时间的同步操作安装Prometheus之前必须要先安装ntp时间同步&#xff0c;因为prometheus server对系统时间的准确性要求很高&#xff0c;必须保证本机时间实时同步。# 用crontab进行定时的时间的同步 yum …

RabbitMQ—TTL、死信队列、延迟队列

上篇文章&#xff1a; RabbitMQ—消息可靠性保证https://blog.csdn.net/sniper_fandc/article/details/149311576?fromshareblogdetail&sharetypeblogdetail&sharerId149311576&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 目录 1 TTL …