Vue3 中 ref 和 reactive 的区别?什么时候用哪个?

ref

将任何类型的值变成响应式,通过 .value 访问。

const count = ref(0)
const name = ref('Tom')
const obj = ref({ a: 1 })

count.value++         // 修改
console.log(count.value)  // 1
obj.value.a = 2       // 修改对象属性

reactive

将对象变成响应式(Proxy 代理),直接访问属性。

const state = reactive({
  count: 0,
  name: 'Tom'
})

state.count++         // 直接修改
console.log(state.count)  // 1

核心区别

特性 ref reactive
支持类型 所有类型(原始+对象) 仅对象/数组
访问方式 .value 直接访问属性
解构 ❌ 失去响应式 ❌ 失去响应式
模板中 自动解包,不需要 .value 直接使用
重新赋值 ✅ ref.value = newVal ❌ 直接赋值失去响应式
深层响应 ✅ ✅

reactive 的陷阱

1. 解构丢失响应式

const state = reactive({ count: 0, name: 'Tom' })
const { count } = state  // ❌ count 不再是响应式
count++  // 不触发更新

// ✅ 解决:toRefs
const { count, name } = toRefs(state)
count.value++  // 响应式

2. 重新赋值丢失响应式

let state = reactive({ list: [] })
state = reactive({ list: [1, 2] })  // ❌ 新对象不是代理

// ✅ 解决:修改属性
state.list = [1, 2]

// ✅ 或用 ref
const state = ref({ list: [] })
state.value = { list: [1, 2] }  // ✅

什么时候用 ref

// 原始类型
const count = ref(0)
const text = ref('')

// 需要整体替换的对象
const user = ref(null)
user.value = await fetchUser()  // ✅

// DOM 引用
const inputRef = ref(null)

什么时候用 reactive

// 一组相关的状态
const form = reactive({
  username: '',
  password: '',
  remember: false
})

// 不需要整体替换的对象
const config = reactive({
  api: '/api/v1',
  timeout: 5000
})

最佳实践

模板中的自动解包

<template>
  <!-- ref 自动解包,不需要 .value -->
  <div>{{ count }}</div>
  <div>{{ state.count }}</div>
</template>

同分类其他题目