1️⃣ reactiveref 的基本概念

reactive

  • 用于 创建响应式对象(通常是对象或数组)。

  • 递归地把对象的每个属性都变成响应式

  • 常用于对象、数组、Map、Set 等。

import { reactive } from 'vue'

const state = reactive({
  count: 0,
  info: { name: 'Vue' }
})

// 使用
state.count++          // count 改变,视图会更新
state.info.name = 'Vue3'  // info.name 改变,视图会更新

特点:

  • 对象和数组适合用 reactive

  • 直接访问属性即可,无需 .value


ref

  • 用于 创建一个包含单一值的响应式引用

  • ref 返回的是一个 对象,有一个 .value 属性保存实际的值。

  • 可以用来保存 基本类型数据string, number, boolean),也可以保存对象、数组

import { ref } from 'vue'

const count = ref(0)

// 使用
count.value++       // 必须用 .value,视图才会更新

// ref 包含对象
const info = ref({ name: 'Vue' })
info.value.name = 'Vue3'  // 对象内部修改同样响应式

特点:

  • 基本类型一定要用 ref 才能响应式。

  • 访问值需要 .value

  • 组合式 API中常用 ref 来单独管理简单数据。


2️⃣ 为什么 ref 要用 .value

核心原因:

  • ref 本身是一个 对象包装器,它内部包含了一个响应式引用。

  • Vue 通过这个对象来 跟踪依赖,实现响应式更新。

  • 如果直接操作基本类型而不通过 .valueVue 无法劫持变化

       拓展:什么是“劫持变化”?

       在 Vue3 里,响应式的核心就是 数据劫持

  •    Vue 会在你访问/修改数据的时候 拦截操作,收集依赖,通知组件更新。

  •    这个拦截主要依靠 Proxy(对对象) getter/setter(对 ref 的 .value来实现。

  • JavaScript 的基本类型(number、string、boolean、null、undefined、symbol、bigint)是 值类型,不是对象。

  • 它们没有 getter/setter,可以直接赋值。

  • 所以 Vue 没法直接拦截 let count = 0 这种变化。

举例:

const count = ref(0)

// Vue 内部类似这样
// count = { value: 0, __v_isRef: true }

所以访问或修改必须写成:

count.value = 5
console.log(count.value)

如果你写成 count = 5

  • 只是给变量 count 重新赋值,并不会触发 Vue 的响应式更新

提示:如果是对象类型,访问对象的属性不需要 .value,但访问 ref 本身仍需要 .value


3️⃣ reactiveref 的对比总结

特性reactiveref
用途对象/数组基本类型或对象引用
返回值响应式对象本身.value 的对象
修改方式state.count = 1count.value = 1,info.value.name='青年'
嵌套属性自动递归响应对象需通过 .value 访问属性
适用场景状态对象/复杂数据单一数据或简单引用

4️⃣ 小技巧

  • 如果你想把基本类型的 ref 当作普通变量使用,可以用 解构 + toRefsunref

import { ref, unref } from 'vue'

const count = ref(0)
console.log(unref(count)) // 输出 0
  • Vue 模板中可以直接使用 ref,无需 .value

<template>
  <p>{{ count }}</p>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

💡 总结

  1. reactive 用于对象/数组,访问属性直接用。

  2. ref 用于基本类型或引用,访问或修改必须 .value

  3. Vue 内部通过 .value 对 ref 进行响应式劫持。

更多推荐