1. 基本定义
- 在Vue3中的Composition API中,ref和reactive都是用来创建响应式数据的核心函数
| 函数 | 作用 |
|---|
ref | 用于创建一个响应式的引用对象,适用于基本类型(string/number/boolean) 或 单个值 |
reactive | 用于创建一个响应式的对象(或数组),对对象/数组进行深层响应式包装 |
- 使用数据类型不同
-
- ref:适合基本类型+单个值
import { ref } from 'vue'
const count = ref(0)
const name = ref('Alice')
const isLoading = ref(false)
-
- reactive: 只适合对象/数组
import { reactive } from 'vue'
const state = reactive({
count: 0,
name: 'Alice',
items: [1, 2, 3]
})
- 其中不能用reactive(0) 或reaxctive('hello')会报错
- 访问和修改方式不同
| 读取值 | 修改值 |
|---|
ref | count.value | count.value = 1 |
reactive | state.count | state.count = 1 |
const count = ref(0)
const state = reactive({ count: 0 })
console.log(count.value)
console.log(state.count)
count.value++
state.count++
count = 1
- 在模版中,Vue会自动解包count,所以可以直接写{{ count }},不用 .value 。
- 替换整个对象的能力
const user = ref({ name: 'Tom' })
user.value = { name: 'Jerry' } // ✅ 完全替换,响应式依然有效
const user = reactive({ name: 'Tom' })
user = { name: 'Jerry' } // ❌ 报错!user 是常量,且失去响应式
如果想重置,必须逐个属性赋值:
Object.assign(user, { name: 'Jerry' })
- 内部实现机制
| 内部结构 | 响应式原理 |
|---|
ref | { value: ... }包装对象 | 通过 .value的 getter/setter 触发依赖收集 |
reactive | Proxy 代理原对象 | 使用 ES6 Proxy拦截对象所有属性的读写 |
- ref本质上是对. value 属性做响应式
- reactive 是对整个对象做深层代理
- 在模版中的使用体验
- 两者在模板中几乎无差别,因为 Vue 会自动解包
ref:
<template>
<p>{{ count }}</p>
<p>{{ state.count }}</p>
</template>
<script setup>
import { ref, reactive } from 'vue'
const count = ref(0)
const state = reactive({ count: 0 })
</script>
2. 如何选择以及使用建议
| 场景 | 推荐 |
|---|
| 基本类型(数字、字符串、布尔值) | ✅ ref |
| 单个对象/数组,且不需要频繁替换整个对象 | ✅ reactive |
| 需要传递给子组件(props / emit) | ✅ ref(更灵活) |
| 返回多个响应式变量(组合函数) | ✅ ref(方便解构) |
| 大型状态对象(如 store) | ✅ reactive(结构清晰) |
- 不确定的时候,优先使用ref调用(更通用,更安全
- 管理复杂对象的时候,用reactive(代码更简洁
3. 常见误区
3.1. reactive 可以监听基本类型?
const num = reactive(0)
3.2. 在setup()外直接用ref值?
const count = ref(0)
setInterval(() => {
count++
}, 1000)
3.3. 解构 reactive 会失去响应式
const state = reactive({ count: 0 })
const { count } = state
import { toRefs } from 'vue'
const { count } = toRefs(state)
| 特性 | ref | reactive |
|---|
| 适用类型 | 基本类型、对象、数组 | 仅对象、数组 |
| 访问方式 | .value | 直接属性访问 |
模板中是否需 .value | ❌ 自动解包 | ❌ 直接用 |
| 可整体替换 | ✅ | ❌(需用 Object.assign) |
| 解构是否保持响应式 | ✅(本身就是独立 ref) | ❌(需 toRefs) |
| 内部实现 | { value: ... } + getter/setter | Proxy 代理 |
| 推荐场景 | 通用、简单值、组合函数返回 | 复杂状态对象 |