Vue 3 常用响应式数据类型详解:ref、reactive、toRef 和 toRefs

Vue 3 常用响应式数据类型详解:ref、reactive、toRef 和 toRefs

1. ref() - 响应式引用

基本概念

ref 是 Vue 3 中最基础的响应式 API,用于创建一个包含响应式数据的引用对象。

核心特点

  • 可以包装任何值类型(基本类型、对象、数组等)
  • 通过 .value 属性访问和修改值
  • 模板中自动解包(不需要写 .value

使用示例

javascript 复制代码
import { ref } from 'vue'

// 基本类型
const count = ref(0)
console.log(count.value) // 0
count.value++ // 修改值

// 对象类型
const user = ref({ name: '张三', age: 25 })
console.log(user.value.name) // '张三'
user.value.age = 26 // 修改嵌套属性

// 模板中使用(自动解包)
// <div>{{ count }}</div>
// <div>{{ user.name }}</div>

适用场景

  • 基本数据类型(字符串、数字、布尔值等)
  • 需要完全替换引用的对象
  • 需要明确区分响应式和非响应式数据时

2. reactive() - 响应式对象

基本概念

reactive 用于创建深度响应式的对象(包括数组、Map、Set 等集合类型)。

核心特点

  • 返回对象的 Proxy 代理
  • 嵌套对象也是响应式的
  • 不需要 .value 访问
  • 解构或展开会失去响应性

使用示例

javascript 复制代码
import { reactive } from 'vue'

const state = reactive({
  count: 0,
  user: {
    name: '李四',
    age: 30
  },
  hobbies: ['阅读', '编程']
})

// 直接访问和修改
console.log(state.count) // 0
state.count++

// 嵌套对象也是响应式的
state.user.name = '王五'

// 数组操作也是响应式的
state.hobbies.push('游泳')

适用场景

  • 复杂的对象结构
  • 需要深度响应式的场景
  • 需要管理多个相关状态时

3. toRef() - 转换为单个 ref

基本概念

toRef 用于从 reactive 对象中提取单个属性并保持响应性连接。

核心特点

  • 保持与源属性的响应式连接
  • 修改会双向影响源对象
  • 即使源属性不存在也会创建 ref

使用示例

javascript 复制代码
import { reactive, toRef } from 'vue'

const state = reactive({
  count: 0,
  name: '张三'
})

// 将响应式对象的属性转为ref
const countRef = toRef(state, 'count')

// 修改会双向影响
countRef.value++
console.log(state.count) // 1

state.count++
console.log(countRef.value) // 2

// 即使属性不存在也会创建ref
const nonExistRef = toRef(state, 'nonExist')
nonExistRef.value = '新值' // 会添加到原对象
console.log(state.nonExist) // '新值'

适用场景

  • 需要将 reactive 对象的某个属性单独传递时
  • 需要确保属性访问的响应性时
  • 组合式函数中返回单个属性时

4. toRefs() - 转换为多个 ref

基本概念

toRefs 将 reactive 对象转换为普通对象,但每个属性都是 ref。

核心特点

  • 保持所有属性的响应式连接
  • 方便解构而不失去响应性
  • 常用于组合式函数返回值

使用示例

javascript 复制代码
import { reactive, toRefs } from 'vue'

const state = reactive({
  count: 0,
  name: '张三'
})

// 转换为ref对象
const stateRefs = toRefs(state)
/*
{
  count: Ref<number>,
  name: Ref<string>
}
*/

// 解构后仍保持响应性
const { count, name } = toRefs(state)
count.value++
console.log(state.count) // 1

// 组合式函数中使用
function useFeature() {
  const state = reactive({ x: 0, y: 0 })
  return toRefs(state) // 调用方可以解构而不失去响应性
}

const { x, y } = useFeature()

适用场景

  • 从组合式函数返回 reactive 对象时
  • 需要解构 reactive 对象但保持响应性时
  • 需要将 reactive 对象的属性批量传递给子组件时

对比总结

特性 ref reactive toRef toRefs
创建方式 ref(value) reactive(obj) toRef(obj, key) toRefs(obj)
值访问 需要 .value 直接访问 需要 .value 每个属性需要 .value
模板使用 自动解包 直接使用 自动解包 每个属性自动解包
主要用途 基本类型/对象引用 复杂响应式对象 提取单个响应式属性 解构响应式对象
响应性保持 完全响应式 深度响应式 保持与源连接 保持所有属性连接

最佳实践建议

  1. 基础选择原则

    • 简单数据用 ref
    • 复杂对象用 reactive
    • 需要解构用 toRefs
  2. 组合式函数

    • 返回响应式数据时优先使用 toRefs
    • 这样调用方可以自由解构
  3. 性能考虑

    • 大型对象使用 reactive 比多个 ref 更高效
    • 不需要深度响应式时考虑 shallowRef/shallowReactive
  4. 代码组织

    • 相关状态组织在一个 reactive 对象中
    • 独立值使用 ref
  5. 类型安全

    • refreactive 提供 TypeScript 类型注解
    typescript 复制代码
    const count = ref<number>(0)
    const state = reactive<{name: string, age: number}>({name: '', age: 0})

这些响应式 API 是 Vue 3 组合式 API 的核心,理解它们的特性和适用场景对于开发高效的 Vue 应用至关重要。

相关推荐
年纪轻轻就扛不住2 分钟前
CSS3 渐变效果
前端·css·css3
Aisanyi6 分钟前
【鸿蒙开发】使用HMRouter路由的使用
前端·harmonyos
杉木笙11 分钟前
Flutter 代码雨实现(矩阵雨)DLC 多图层
前端·flutter
SouthernWind12 分钟前
Vista AI 演示—— 提示词优化功能
前端·vue.js
林太白13 分钟前
也许看了Electron你会理解Tauri,扩宽你的技术栈
前端·后端·electron
前端的日常16 分钟前
JavaScript 必看!算法 O 系列全攻略
前端
anganing20 分钟前
Web 浏览器预览 Excel 及打印
前端·后端
Chad21 分钟前
Vue3 + vite 首屏优化加载速度
前端
Ace_317508877631 分钟前
义乌购平台店铺商品接口开发指南
前端
ZJ_34 分钟前
Electron自动更新详解—包教会版
前端·javascript·electron