源本科技 | 码上会

Vue3 响应式系统

2026/04/21
2
0

引言

Vue 3 的响应式系统基于 ES6 Proxy 实现,相比 Vue 2 的 Object.defineProperty,具备更完善的拦截能力:可监听对象 / 数组的新增、删除、修改等所有操作,彻底告别 $set 等兼容 API。同时搭配效应调度系统,保证数据变更时视图精准更新,极大简化了复杂数据的交互处理,是组合式 API 的核心基石。

响应式状态 ref

ref() 是组合式 API 中官方首选的响应式声明方式,适用于所有数据类型(基本类型、对象、数组均可),通过创建响应式引用实现数据监听。

核心特性

  • 包装基本数据类型(string / number / boolean / null / undefined),弥补 Proxy 无法代理基本类型的缺陷

  • 支持深度响应式,自动监听嵌套对象 / 数组的变化

  • 脚本中访问 / 修改需通过 .value,模板中会自动解包(无需写 .value

  • 完美支持 TypeScript 泛型,类型推导更安全

基本用法

import { ref } from 'vue'

// 声明响应式数据
const count = ref(0)

// 脚本中必须通过 .value 访问和修改
console.log(count.value) 
count.value++
console.log(count.value) 

泛型类型标注

ref 指定泛型,获得更严格的类型校验(Vue 3 + TypeScript 标准写法):

// 支持多类型
const year = ref<string | number>('2024')
year.value = 2025 

// 未初始化,指定类型
const num = ref<number>() 

组件实践

<template>
  <div>
    <!-- 模板中自动解包,无需 .value -->
    <button @click="count++">Count is: {{ count }}</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
// 声明数字类型响应式变量
const count = ref<number>(0)
</script>

<style scoped>
</style>

深度响应性

ref 支持对象、数组等复杂类型,默认深度监听内部所有属性变化:

<template>
  <div>
    <p>用户名:{{ user.username }}</p>
    <p>密码:{{ user.password }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

// 定义类型,替代不安全的 any
interface User {
  username: string
  password: string
}

// 响应式对象
const user = ref<User>({
  username: 'admin',
  password: '123456'
})

// 脚本中访问嵌套属性
console.log(user.value.username)
</script>

响应式对象 reactive

reactive() 是 Vue 3 提供的对象专属响应式 API,仅适用于引用类型(对象、数组、Map/Set 等),直接返回一个代理对象。

核心特性

  • 仅支持对象 / 数组,不支持基本数据类型

  • 无需 .value,直接访问 / 修改属性

  • 天然深度响应式,适合管理多属性的复杂状态

  • 解构会丢失响应式(需配合 toRefs / toRef 解决)

基本用法

<template>
  <div>
    <p>计数:{{ state.count }}</p>
    <p>用户名:{{ state.user.username }}</p>
  </div>
</template>

<script setup lang="ts">
import { reactive } from 'vue'

// 定义类型
interface User {
  username: string
}
interface State {
  count: number
  user: User
}

// 创建响应式对象
const state = reactive<State>({
  count: 0,
  user: {
    username: 'admin'
  }
})

// 直接访问属性,无需 .value
console.log(state.count)
console.log(state.user.username)
</script>

ref 与 reactive

特性

ref

reactive

支持类型

所有类型(基本类型 + 引用类型)

仅引用类型(对象 / 数组)

访问方式

脚本需 .value,模板自动解包

直接访问属性

解构赋值

可直接解构,保留响应式

解构丢失响应式

重新赋值

支持直接重新赋值

不支持直接重新赋值(会脱离代理)

最佳实践

  1. 优先使用 ref:通用、灵活,适配所有场景,是日常开发的首选

  2. reactive 适用场景:管理强关联的多字段状态(如表单对象、分页参数)

  3. 禁止使用 any:配合 TypeScript 定义接口,保证类型安全

  4. 复杂数据ref 包装对象完全可以替代 reactive