在 Vue 中,reactive 和 ref 都是创建响应式数据的核心 API,但它们的适用场景有所不同,选择依据主要取决于数据类型使用习惯

1. 用 ref 的场景

ref 主要用于处理基本数据类型(字符串、数字、布尔值等),也可以用于对象 / 数组(内部会自动转换为 reactive 代理)。
核心特点:通过 .value 访问 / 修改值,适合简单数据或需要单独管理的状态。

典型场景:

  • 基本类型数据

const count = ref(0)       // 数字
const name = ref('张三')   // 字符串
const isVisible = ref(true) // 布尔值
  • 需要单独管理的简单状态
    如组件中的开关状态、计数器、加载状态等独立变量:


const loading = ref(false)
const error = ref(null)
const currentTab = ref('home')
  • 在模板中直接使用
    模板中无需 .value,Vue 会自动解包,使用更简洁:


<template><div>{{ count }}</div> <!-- 直接使用,无需 .value -->
</template>
  • 需要作为响应式数据传递给函数
    由于 ref 是一个包装对象,传递时能保持响应性(避免基本类型的 "值传递" 丢失响应性):

function increment(num) {num.value++ // 能正确修改原始 ref 的值
}
increment(count)

2. 用 reactive 的场景

reactive 用于处理复杂对象或数组,将整个对象转换为响应式代理,适合聚合管理多个相关属性。
核心特点:直接访问属性(无需 .value),但不能用于基本类型。

典型场景:

  • 多属性的复杂对象
    如用户信息、表单数据等包含多个字段的结构:

const user = reactive({name: '张三',age: 25,address: { city: '北京' } // 支持嵌套对象
})
  • 聚合相关状态
    将逻辑关联的状态放在一起,使代码更有条理:


const form = reactive({username: '',password: '',rememberMe: false
})
  • 数组或集合类型
    管理列表数据时,reactive 可以直接处理数组的响应式:

const list = reactive([{ id: 1, name: 'item1' },{ id: 2, name: 'item2' }
])
list.push({ id: 3, name: 'item3' }) // 响应式更新
  • 避免过多 ref 变量
    当组件状态较多时,用 reactive 聚合比声明多个 ref 更简洁:


// 优于:const a = ref(1); const b = ref(2); const c = ref(3)
const state = reactive({a: 1,b: 2,c: 3
})

3. 核心区别与选择原则

维度

ref

reactive

适用类型

基本类型、对象、数组

仅对象 / 数组(非基本类型)

访问方式

需要 .value(脚本中)

直接访问属性

解构特性

解构后仍可保持响应性

直接解构会丢失响应性

替换整个数据

可以(ref.value = 新值

不可以(会破坏代理)

选择原则:

  • 简单值用 ref:数字、字符串、布尔等基本类型,或独立的简单状态。
  • 复杂对象用 reactive:多属性对象、数组,或需要聚合管理的相关状态。
  • 优先 ref:如果不确定用哪个,ref 更通用(可处理所有类型),尤其在 Composition API 中更常用。

4. 常见错误与注意事项

  • 不要用 reactive 处理基本类型(无效):



const count = reactive(0) // 错误!reactive 对基本类型无效
  • reactive 对象直接赋值会丢失响应性:


const user = reactive({ name: '张三' })
user = { name: '李四' } // 错误!这样会覆盖代理对象,失去响应性
  • 解构 reactive 对象需用 toRefs 保持响应性:


import { toRefs } from 'vue'
const { name, age } = toRefs(user) // 解构后仍有响应性


通过合理区分使用场景,可以让响应式数据的管理更清晰、高效。