在 Vue3 中,我们拥有了两个创建响应式数据的 API:
-
ref -
reactive
于是,几乎所有初学者都会遇到同一个问题:
❓ 什么时候用 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) // 1
2️⃣ 为什么 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 的高级玩法

1751

被折叠的 条评论
为什么被折叠?



