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
})最佳实践
- 简单值(数字、字符串、布尔) → ref
- 需要替换的对象(如 API 返回的数据) → ref
- 一组相关状态 → reactive + toRefs
- 不确定 → ref(更安全、更一致)
模板中的自动解包
<template>
<!-- ref 自动解包,不需要 .value -->
<div>{{ count }}</div>
<div>{{ state.count }}</div>
</template>