《Vue3 从入门到大神06篇》ref 还是 reactive?一文搞懂响应式数据的选择
在 Vue3 中,我们拥有了两个创建响应式数据的 API:
refreactive
于是,几乎所有初学者都会遇到同一个问题:
❓什么时候用 ref?什么时候用 reactive?
❓为什么 ref 要写
.value?❓为什么解构会丢失响应式?
这篇文章,我们就来一次把这些疑问彻底讲清楚。
一、一句话结论(先给你答案)
数据类型 | 推荐 API |
|---|---|
基本类型(string / number / boolean) | ✅ |
对象 / 数组 | ✅ |
表单字段 / 单个状态 | ✅ |
复杂状态对象 | ✅ |
📌经验法则:
能用 ref 解决的,就用 ref;复杂对象再用 reactive。
二、ref:为基本类型而生
1️⃣ ref 的基本用法
import { ref } from 'vue' const count = ref(0) count.value++ console.log(count.value) // 12️⃣ 为什么 ref 需要.value?
因为:
JavaScript 的基本类型不是对象,不能被 Proxy 直接代理。
Vue3 的解决方案是:
ref(0) → { value: 0 }📌ref 本质:
用一个对象包裹基本类型
对这个对象的
value做响应式处理
三、reactive:为引用类型而生
1️⃣ reactive 的基本用法
import { reactive } from 'vue' const state = reactive({ count: 0, user: { name: 'Tom' } })2️⃣ 使用方式
state.count++ state.user.name = 'Jerry'✅不需要.value
✅可以直接访问属性
四、ref 和 reactive 的本质区别
对比项 | ref | reactive |
|---|---|---|
包装方式 |
| Proxy |
支持类型 | 基本 + 引用 | 仅引用 |
| 必须 | 不需要 |
替换整个对象 | ✅ 支持 | ❌ 丢失响应式 |
解构 | ❌ 易丢响应式 | ✅ 可直接解构 |
五、.value的底层原理(面试重点)
1️⃣ ref 的简化实现
function ref(value) { const wrapper = { value } return reactive(wrapper) }📌核心思想:
ref内部其实也用了reactive只是多包了一层
value
六、解构为什么会丢失响应式?(非常重要)
1️⃣ 错误示例
const state = reactive({ count: 0 }) const { count } = state count++ // ❌ 不再是响应式2️⃣ 原因图解
state.count → Proxy count → 普通数字(脱离 Proxy)📌结论:
解构得到的是“值本身”,不是“代理引用”。
七、如何正确解构响应式数据?
✅ 方案 1:toRefs
import { reactive, toRefs } from 'vue' const state = reactive({ count: 0 }) const { count } = toRefs(state) count.value++✅ 方案 2:保持 state 不变
state.count++八、ref 和 reactive 的常见误区
❌ 误区 1:reactive 可以替换 ref
const count = reactive({ value: 0 }) // ❌ 不推荐📌原因:语义混乱,不符合 Vue 设计初衷。
❌ 误区 2:ref 不能包对象
const user = ref({ name: 'Tom' })✅这是允许的,但注意:
user.value.name = 'Jerry'九、实战选择建议(强烈建议收藏)
✅ 表单场景
const username = ref('') const password = ref('')✅ 复杂业务对象
const user = reactive({ id: 1, name: '', roles: [] })✅ 组合式函数返回
function useCounter() { const count = ref(0) const inc = () => count.value++ return { count, inc } }十、面试高频问答
Q1:ref 为什么要.value?
因为基本类型不能被 Proxy 代理,需要包一层对象。
Q2:reactive 解构为什么会失效?
解构得到的是原始值,脱离了 Proxy。
Q3:什么时候用toRefs?
当你需要把 reactive 拆成多个 ref 使用时。
十一、总结
ref:基本类型 + 单个状态reactive:复杂对象.value是 ref 的设计必然解构 reactive 会丢失响应式
toRefs是解决手段
📢 下期预告
👉第 07 篇:计算属性与侦听器 —— computed 与 watch 的高级玩法
