主题
Vue 3 响应式 API 深入解析:reactive、ref、toRef、toRefs
Vue 3 提供了丰富的响应式 API,让状态管理更加灵活。本文介绍四个核心 API:reactive
、ref
、toRef
、toRefs
,重点分析 区别、使用场景,并给出常见错误示例。
1️⃣ reactive
- 作用:将对象或数组转换为响应式对象(深层响应式)。
- 适用场景:
- 对象或数组需要整体响应式
- 包含嵌套对象或数组,修改内部属性也希望触发更新
- 特点:
- 返回一个 Proxy
- 深层响应式
- 不适合基本类型(number、string、boolean)
正确示例:
js
import { reactive } from 'vue'
const state = reactive({
count: 0,
info: { name: 'Alice' }
})
state.count++ // 响应式更新
state.info.name = 'Bob' // 深层响应式
错误示例(对基本类型无效):
js
const count = reactive(0) // ❌ 不会成为响应式
2️⃣ ref
作用:为基本类型或对象创建响应式引用
适用场景:
- 基本类型(number、string、boolean)
- 对象也可用 ref 包裹,但内部对象不是深层响应式(除非用 reactive 包裹)
访问/修改:通过
.value
正确示例:
js
import { ref, reactive } from 'vue'
const count = ref(0)
count.value++ // 响应式更新
const obj = ref({ name: 'Alice' })
obj.value.name = 'Bob' // 对象内部也可修改
错误示例(解构后失去响应式):
js
const obj = ref({ name: 'Alice' })
const { name } = obj.value
name = 'Bob' // ❌ 不会触发响应式更新
3️⃣ toRef
作用:将响应式对象的单个属性转换为 ref
适用场景:
- 需要单独解构对象的某个属性,同时保持响应式
特点:
- 修改 ref.value 会同步到原对象
- 避免响应式丢失问题
正确示例:
js
import { reactive, toRef } from 'vue'
const state = reactive({ count: 0 })
const countRef = toRef(state, 'count')
countRef.value++ // state.count 同步更新
错误示例(直接解构属性):
js
const { count } = state // ❌ count 不是 ref,解构后丢失响应式
count++ // 不会更新 state.count
4️⃣ toRefs
作用:将响应式对象的所有属性都转换为 ref,返回对象
适用场景:
- 解构对象后仍希望保持响应式
特点:
- 每个属性变成 ref
- 修改 ref.value 会同步到原对象
正确示例:
js
import { reactive, toRefs } from 'vue'
const state = reactive({ count: 0, name: 'Alice' })
const { count, name } = toRefs(state)
count.value++ // state.count 同步更新
name.value = 'Bob' // state.name 同步更新
错误示例(解构 reactive 对象直接赋值):
js
const { count, name } = state // ❌ 不使用 toRefs
count++ // 不会触发响应式
5️⃣ 区别与总结
API | 适用类型 | 响应式深度 | 解构安全 | 使用场景 |
---|---|---|---|---|
reactive | 对象/数组 | 深层 | ❌ | 整体对象响应式,嵌套属性响应 |
ref | 基本类型/对象 | 单层 | ❌ | 单值响应式,基本类型或对象引用 |
toRef | 对象单个属性 | 单层 | ✅ | 解构单个属性仍保持响应式 |
toRefs | 对象所有属性 | 单层 | ✅ | 解构对象后仍保持所有属性响应式 |
✅ 小结
- reactive:对象/数组整体响应式
- ref:基本类型或单个对象引用
- toRef:单个属性解构安全
- toRefs:多个属性解构安全
TIP
对象解构后要保持响应式,必须使用 toRef
或 toRefs
。
基本类型一定要用 ref
,不能直接用 reactive
。
使用不当(解构 reactive 或 ref.value 内部对象)会丢失响应式。