Vue中的ref和reactive到底在干嘛

ref

1. 先搞懂一个核心问题:Vue 怎么知道你改了数据,然后刷新页面?

Vue 需要盯着你的变量,一变就自动更新网页上显示的内容。

普通变量 Vue 盯不住:

ts 复制代码
let num = 1
num = 2

Vue:完全没感知,页面数字不会变。

2. ref 干的唯一一件事:给变量套一层「监控外壳」

ref(里面的值) 会生成一个外壳对象,Vue 专门盯着这个外壳。

ts 复制代码
import { ref } from 'vue'
const num = ref(1)

底层真实结构可以理解成这样:

js 复制代码
num = {
  // 真正存数字的地方
  value: 1,
  // Vue偷偷藏了监听代码
}
  • 外壳 num Vue能看见、能监控;
  • 真正的数据藏在 .value 里面。

改数据的时候,必须改 .value

ts 复制代码
num.value = 2

Vue 检测到你修改了外壳里的 value,立刻刷新页面。

如果你写成 num = 2,直接把整个监控外壳扔掉了,Vue 失去监控,页面不动。

3. 模板里为什么不用 .value?

模板是 Vue 单独处理的语法,它会自动帮你读取 .value。

vue 复制代码
<!-- 不用写 num.value -->
<div>{{ num }}</div>

4. 最简可运行对比,一眼看出差别

例子1:不用 ref(页面不更新)

js 复制代码
<script setup>
let count = 0
function add() {
  count++
  console.log(count) // 控制台数字变了,页面不动
}
</script>

<template>
  <p>数字:{{ count }}</p>
  <button @click="add">点我+1</button>
</template>

例子2:用 ref(页面同步更新)

js 复制代码
<script setup>
import { ref } from 'vue'
// 套监控外壳
const count = ref(0)
function add() {
  // 修改外壳内部的值
  count.value++
}
</script>

<template>
  <p>数字:{{ count }}</p>
  <button @click="add">点我+1</button>
</template>

5. ref 第二个用途:获取页面DOM标签

你想操作页面上的输入框、按钮,JS原生拿DOM很麻烦,用ref绑定:

js 复制代码
<script setup>
import { ref, onMounted } from 'vue'
// 空的监控外壳,专门存input元素
const inputDom = ref(null)

// 页面渲染完后
onMounted(() => {
  // inputDom.value 就是页面里的input标签
  inputDom.value.focus() // 自动光标聚焦输入框
})
</script>

<template>
  <!-- ref名字和变量对应 -->
  <input ref="inputDom" placeholder="搜索" />
</template>

Vue 把 ref 做成了模板特殊指令,自动帮你完成「查找 DOM、存入变量」这一步,不用手写 querySelector,这是框架封装出来的语法。

补充对比:

js 复制代码
<input id="searchInput" placeholder="搜索">

<script>
// 原生必须手动根据id获取DOM
const input = document.getElementById('searchInput')
// 页面加载完才能操作
window.onload = function() {
  input.focus()
}
</script>

Vue 简化后,不用写选择器,靠同名 ref 自动绑定,是框架提供的便利语法。

6. 一句话终极总结

ref = 给数字/字符串/布尔/DOM标签包一层 Vue 能监控的外壳;

代码里改值要 .value,模板里直接写变量名。

reactive

1. reactive 和 ref 是亲兄弟,作用一样:让数据变响应式,改了页面自动更新

区别只在于装的数据类型不一样:

  • ref:装单个简单值(数字、字符串、布尔、DOM),要用 .value
  • reactive:专门装 对象、数组 ,不用写 .value

2. 先看对比,一眼看懂

场景1:表单对象,用 reactive

ts 复制代码
import { reactive } from 'vue'

// 把整个表单变成响应式
const form = reactive({
  filename: '',
  status: '',
  id: 0
})

// 直接点属性修改,不用 .value
form.filename = '测试文档.pdf'
form.status = 'success'

场景2:如果硬用 ref 写对象(麻烦)

ts 复制代码
const form = ref({
  filename: ''
})
// 修改必须两层 .value,很啰嗦
form.value.filename = 'xxx'

3. reactive 底层原理

ref 是套一层 { value: xxx }

reactive 直接把整个对象本身变成可监听代理 ,不用包一层盒子,所以不用 .value。

4. 数组也用 reactive

ts 复制代码
const docList = reactive<DocumentRead[]>([])
// 直接push、修改数组,页面自动刷新
docList.push({ id: 1, filename: 'a.pdf', status: '' })

5. 核心优缺点

优点

修改属性简洁,不用每次打 .value,表单、列表首选。

大坑(重点)

不能直接替换整个对象!会丢失响应式

ts 复制代码
const form = reactive({ name: '' })

// ❌ 错误,直接覆盖整个对象,Vue 失去监听
form = { name: '新名字' }

// ✅ 正确,只改里面属性
form.name = '新名字'

ref 就没这个问题:

ts 复制代码
const form = ref({ name: '' })
// 可以直接替换 .value
form.value = { name: '新名字' }

6. ref 和 reactive 选择口诀

  1. 单个数字/字符串/布尔 / DOM引用 → ref
  2. 表单、JSON对象、列表数组 → reactive

7. 配套工具 toRefs(高频搭配 reactive)

如果你想把 reactive 对象拆分成单独变量,不丢失响应式:

ts 复制代码
import { reactive, toRefs } from 'vue'

const form = reactive({ name: '', id: 1 })
// 解构出独立ref变量
const { name, id } = toRefs(form)

// 此时 name、id 是 ref,修改需要 .value
name.value = '张三'

一句话总结

reactive 是 Vue 提供的API,专门把对象、数组转为响应式,直接 .属性 修改,不用写 .value;适合表单、列表这种复杂结构数据。

相关推荐
卸任23 分钟前
Vibe coding工具使用心得
前端·ai编程
brien91 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance1 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M1 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写2 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李2 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易2 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding2 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马2 小时前
前沿视界
前端
kyriewen2 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员