在 Vue 3 中,refreactive 都是用于声明响应式变量的 API,核心作用是让变量的变化能够被 Vue 追踪,从而触发视图更新。但它们的使用场景和特性有明显区别,具体如下:

1. 处理的数据类型不同

  • ref
    用于包装基本数据类型(String、Number、Boolean、Null、Undefined)和引用数据类型(Object、Array)。
    本质是创建一个包含 .value 属性的响应式对象,通过 .value 访问或修改值。示例:
import { ref } from 'vue'

// 基本类型
const count = ref(0)
console.log(count.value) // 访问值:0
count.value = 1 // 修改值(必须通过 .value)

// 引用类型
const user = ref({ name: '张三' })
console.log(user.value.name) // 访问:'张三'
user.value.name = '李四' // 修改
  • reactive
    仅用于包装引用数据类型(Object、Array),不能直接包装基本类型(否则会报警告且失去响应性)。
    直接返回一个响应式代理对象,访问/修改时无需 .value。示例:
import { reactive } from 'vue'

// 引用类型(对象)
const user = reactive({ name: '张三', age: 20 })
console.log(user.name) // 访问:'张三'(无需 .value)
user.age = 21 // 修改

// 引用类型(数组)
const list = reactive([1, 2, 3])
list.push(4) // 修改数组

2. 访问/修改方式不同

  • ref
    无论包装什么类型,都必须通过 .value 访问或修改值(在 <template> 模板中使用时,Vue 会自动解包 .value,可直接写变量名)。模板中使用:
<template>
  <div>{{ count }}</div> <!-- 无需 .value,自动解包 -->
</template>
  • reactive
    直接通过对象属性访问/修改,无需 .value,和操作普通对象一样。模板中使用:
<template>
  <div>{{ user.name }}</div> <!-- 直接访问属性 -->
</template>

3. 对引用类型的“响应式深度”不同

  • ref
    包装引用类型时,会自动递归将其转为响应式对象(和 reactive 一样,是“深度响应式”)。
  • reactive
    本身就是深度响应式,对象内部的嵌套属性(即使是多层嵌套)也会被追踪。示例(两者都是深度响应式):
// ref 包装对象
const objRef = ref({ a: { b: 1 } })
objRef.value.a.b = 2 // 响应式生效

// reactive 包装对象
const objReactive = reactive({ a: { b: 1 } })
objReactive.a.b = 2 // 响应式生效

4. 解构/展开后的响应性表现不同

  • ref
    解构后,基本类型的 ref 会失去响应性(因为解构出的是 .value 的值);但引用类型的 ref 解构后,内部属性仍保持响应性(因为本质是 reactive 代理)。示例:
const count = ref(0)
const { value: countVal } = count // 解构基本类型的 ref
countVal = 1 // 不会触发响应式(count.value 仍为 0)

const user = ref({ name: '张三' })
const { value: userVal } = user
userVal.name = '李四' // 会触发响应式(因为 userVal 是 reactive 代理)
  • reactive
    直接解构会丢失响应性(因为解构出的是普通值,不再是代理对象)。如需保持响应性,需用 toRefstoRef 转换。示例:
import { reactive, toRefs } from 'vue'

const user = reactive({ name: '张三', age: 20 })

// 直接解构:失去响应性
const { name, age } = user
name = '李四' // 不会触发响应式

// 用 toRefs 转换后解构:保持响应性
const { name: nameRef, age: ageRef } = toRefs(user)
nameRef.value = '李四' // 触发响应式(需 .value,因为 toRefs 转为了 ref)

5. 使用场景总结

API

适合类型

核心特点

最佳场景

ref

基本类型、引用类型

需通过 .value 访问,模板自动解包

声明基本类型变量;需要单独导出的引用类型

reactive

引用类型(Object/Array)

直接访问属性,无需 .value

声明复杂对象/数组,且需整体操作其属性时

一句话总结

  • 基本类型用 ref,引用类型优先用 reactive(但 ref 也能处理)。
  • 记住 ref.valuereactive 直接用,解构 reactive 时用 toRefs 保响应性。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐