《Vue3 从入门到大神06篇》ref 还是 reactive?一文搞懂响应式数据的选择

在 Vue3 中,我们拥有了两个创建响应式数据的 API:

  • ref

  • reactive

于是,几乎所有初学者都会遇到同一个问题:

什么时候用 ref?什么时候用 reactive?

为什么 ref 要写 .value

为什么解构会丢失响应式?

这篇文章,我们就来一次把这些疑问彻底讲清楚


一、一句话结论(先给你答案)

数据类型

推荐 API

基本类型(string / number / boolean)

ref

对象 / 数组

reactive(或 ref

表单字段 / 单个状态

ref

复杂状态对象

reactive

📌 经验法则

能用 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

包装方式

{ value }

Proxy

支持类型

基本 + 引用

仅引用

.value

必须

不需要

替换整个对象

✅ 支持

❌ 丢失响应式

解构

❌ 易丢响应式

✅ 可直接解构


五、.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 的高级玩法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值