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

Vue 中 ref 和 reactive 有什么区别?该用哪个?

Vue 中 ref 和 reactive 有什么区别?该用哪个?

一句话总结:ref 适合「基本类型 + 需要重新赋值」的场景,reactive 适合「对象/数组 + 不需要整体替换」的场景。记不住?基本类型用 ref,对象用 reactive,需要整体替换的用 ref 包对象,就这么简单!


正文目录

  1. ref 和 reactive 的核心区别是什么?
  2. 5 大高频场景 & 代码示例
  3. 万能兜底:ref vs reactive 决策表
  4. 预防 checklist(不再踩坑)
  5. 一句话总结

一、ref 和 reactive 的核心区别是什么?

问题背景:Vue 3 的响应式系统基于Proxy,提供了refreactive两种创建响应式数据的 API,很多开发者分不清什么时候用哪个。

对比项refreactive
支持类型任意类型(基本类型 + 对象)仅对象/数组
访问方式.value(模板中自动解包)直接访问属性
重新赋值✅ 直接xxx.value = newVal❌ 丢失响应式
解构需要配合toRefs直接解构会丢失响应式
模板中使用自动解包,无需.value直接使用
深层响应✅ 默认深层✅ 默认深层
import{ref,reactive}from'vue'// ✅ ref:基本类型constcount=ref(0)count.value++// JS 中需要 .value// 模板中:{{ count }} 自动解包,不需要 .value// ✅ reactive:对象conststate=reactive({name:'Claw',age:3})state.age=4// 直接修改属性// ❌ reactive 整体替换 → 丢失响应式state=reactive({name:'New',age:5})// 不报错但响应式断了

二、5 大高频场景 & 代码示例

场景 1:计数器 / 开关 → 用 ref

基本类型,需要频繁修改,用 ref 最直观。

// ✅ 正确:基本类型用 refconstisLoading=ref(false)constcount=ref(0)constmessage=ref('hello')functiontoggle(){isLoading.value=!isLoading.value}
// ❌ 错误:reactive 不支持基本类型constcount=reactive(0)// Vue 警告:value should be an object

场景 2:表单对象 → 用 reactive

多个关联字段组成一个对象,不需要整体替换,用 reactive 更自然。

<script setup> import { reactive } from 'vue' // ✅ 表单对象用 reactive const form = reactive({ username: '', password: '', remember: false }) function submit() { console.log(form.username, form.password) } function reset() { // ⚠️ 逐字段重置,不能整体替换 form.username = '' form.password = '' form.remember = false } </script>
// ❌ 错误:整体替换丢失响应式functionreset(){form={username:'',password:'',remember:false}// 响应式断了!}

场景 3:需要整体替换的对象 → 用 ref

从接口拿数据后整体赋值,用 ref 包对象更安全。

// ✅ 正确:接口数据用 ref,方便整体替换constuserInfo=ref(null)asyncfunctionfetchUser(){constres=awaitapi.getUser()userInfo.value=res.data// ✅ 整体替换没问题}
// ❌ 麻烦:reactive 要逐字段赋值constuserInfo=reactive({})asyncfunctionfetchUser(){constres=awaitapi.getUser()Object.assign(userInfo,res.data)// 能用但啰嗦// 或者逐字段:userInfo.name = res.data.name ...}

场景 4:解构响应式对象 → 用 toRefs 配合 reactive

reactive 解构后会丢失响应式,必须用toRefs包装。

<script setup> import { reactive, toRefs } from 'vue' const state = reactive({ name: 'Claw', age: 3 }) // ❌ 直接解构:丢失响应式 // const { name, age } = state // ✅ toRefs 解构:保持响应式 const { name, age } = toRefs(state) </script>
// ref 则不需要 toRefsconstcount=ref(0)// 模板中直接用 {{ count }},无需解构

场景 5:watch 监听 → ref 和 reactive 行为不同
import{ref,reactive,watch}from'vue'// ✅ ref:watch 默认监听 .value 的变化constcount=ref(0)watch(count,(newVal,oldVal)=>{console.log(`${oldVal}${newVal}`)})// ✅ reactive:watch 默认深层监听conststate=reactive({count:0})watch(state,(newVal)=>{console.log('state changed',newVal.count)})// ⚠️ watch reactive 的某个属性 → 需要用 getterwatch(()=>state.count,(newVal,oldVal)=>{console.log(`${oldVal}${newVal}`)})// ⚠️ ref 包对象 → 默认不深层监听,需要 deepconstobj=ref({count:0})watch(obj,(newVal)=>{console.log(newVal)// obj.value = {} 时触发},{deep:true})// 修改 obj.value.count 需要 deep

三、万能兜底:ref vs reactive 决策表

场景用什么原因
基本类型(string/number/boolean)refreactive 不支持基本类型
独立的对象/数组,不需要整体替换reactive访问自然,不需要.value
接口返回的数据,需要整体替换ref可以直接xxx.value = newData
表单对象reactive字段关联,逐字段操作
需要解构使用的对象reactive+toRefsref 不需要解构
定时器/ DOM 引用ref存任意值,不触发渲染
组合式函数返回值ref调用方可以解构后保持响应式

万能决策流程

是基本类型吗? → 是 → 用 ref → 否 → 需要整体替换吗? → 是 → 用 ref(包对象) → 否 → 用 reactive
// 万能模板import{ref,reactive}from'vue'// 基本类型constloading=ref(false)consttotal=ref(0)// 对象 - 不需要整体替换constform=reactive({name:'',email:''})// 对象 - 需要整体替换(接口数据)constlist=ref([])asyncfunctionloadData(){list.value=awaitapi.getList()}

四、预防 checklist(不再踩坑)

  • 基本类型必须用ref,不要用reactive
  • reactive对象不要整体替换,用Object.assign或逐字段赋值
  • 接口数据整体赋值 → 用ref包对象
  • 解构reactive→ 必须用toRefstoRef
  • 模板中ref自动解包,JS 中必须.value
  • watch监听reactive属性 → 用 getter 函数() => state.xxx
  • watch监听ref对象的深层变化 → 加{ deep: true }
  • 组合式函数返回值优先用ref,方便调用方解构

五、一句话总结

基本类型用 ref,固定结构对象用 reactive,需要整体替换的对象用 ref 包裹——记不住就看要不要重新赋值,要重新赋值就用 ref。


最后问候亲爱的朋友们,并邀请你们阅读我的全新著作

📚 《Vue.js 3企业级项目开发实战(微课视频版》

http://www.jsqmd.com/news/1336233/

相关文章:

  • 常州合同纠纷维权实务参考:保全先行与证据链构建,让纸面权益落地 - 本地品牌推荐
  • 网站建设的目标是什么
  • Unity游戏一键发布微信小游戏:WebAssembly适配与性能优化全攻略
  • 法语听力突破临界点突破术:基于Transformer-ASR双模态分析的7天干预方案,限免通道24小时后关闭
  • 2026 年至今,钟楼可靠的短视频获客服务商有哪些,别再花冤枉钱投信息流了,这玩意儿才是实体店抓精准客户的核心抓手? - 品质体验官
  • 2026年叠石桥本地靠谱阳台防水服务商及联系方式实用指南 - 热点品牌推荐
  • 143、LLC谐振变换器的故障记录与诊断
  • 【大白话说Java面试题 第217题】【10_网络协议篇】第8题:GET 和 POST 的区别
  • Python生态绘图类库:Folium、PlotNine、LeafMap、PyGal、CartoPy、floWeaver
  • Microsoft Word、超级简历、100分简历……秋招简历模板哪家强?一篇讲透 - 春日收信人
  • 物联网设备二维码设计:微信扫码背后的技术逻辑与工程实践
  • 2026年天津遗产继承维权指南:六大常见情形应对要点解析 - 本地品牌推荐
  • 常州遗产继承纠纷实务参考:遗嘱效力、房产股权分割与家族财富传承 - 本地品牌推荐
  • 2026 年新发布:前郭尔罗斯蒙古族自治有实力的木箱定制生产厂家哪家靠谱,你家包裹可能还在裸奔,定制这玩意儿竟能护住百万级货物? - 行业严选官
  • 软件测试工程师成长指南:从理论到实践的技能体系构建
  • 向量数据库索引优化:从人工调参到数据驱动的自适应方案
  • 为什么你的企业需要一家靠谱的邯郸网站建设公司?从草根创业到品牌出海的深度思考
  • 对标省统考标准闭环训练 罗丹艺术全真模考助力云南美术联考高分上岸 - 云南美术头条
  • 宁波管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号
  • 借出去的钱怎么要回来?赤峰民间借贷维权路径参考(主推张洛溪律师) - 本地品牌推荐
  • 【大白话说Java面试题 第218题】【10_网络协议篇】第9题:TCP 和 UDP 的主要区别是什么?
  • 天津婚姻家庭律师实务参考:离婚股权分割与家企债务隔离的应对思路 - 本地品牌推荐
  • 无锡管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号
  • 为什么92%的前端工程师还没用上AI?揭秘企业级AI前端落地的4大认知断层与破局公式
  • 哈尔滨管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号
  • 2026年精选:吉林火山岩滤料送货厂商哪家可靠?——八公山区正德轻质建材经营部深度解析 - 装修教育财税推荐2026
  • 构建大模型自动化评测平台:从零实现科学模型对比
  • 电力系统调度中的源荷不确定性建模与优化实践
  • Python零基础入门:2026版全100集教程学习路径与实战指南
  • 平顶山管道疏通公司口碑**:2026年本地正规品牌综合对比与推荐 - 园子一号