VUE3中,reactive()和ref()的区别10分钟讲清楚

在 Vue 3 的组合式 API 中,reactive()和 ref()都是创建响应式数据 的核心 API,但它们的设计目标、适用场景和使用方式有本质区别。

1. 核心定位:处理的数据类型不同

  • reactive() :仅用于包装「对象类型」 (包括普通对象、数组、Map、Set 等),返回一个深层响应式的 Proxy 代理对象。

    它无法直接处理基本类型 (如 string、number、boolean),否则会抛出警告且无效。

  • ref() :可以包装「任意类型」 (基本类型 + 对象类型),返回一个**Ref<T>类型的响应式容器** (本质是带 .value属性的对象)。

    对于对象类型,ref()内部会自动调用 reactive()将其转换为深层响应式 Proxy。

2. 访问方式:是否需要 .value

  • reactive():直接访问对象的属性(无需额外语法)。

    示例:

    复制代码
    import { reactive } from 'vue'
    const user = reactive({ name: 'Alice', age: 20 })
    console.log(user.name) // 直接访问 → "Alice"
    user.age++ // 直接修改 → 响应式更新
  • ref() :必须通过 .value访问或修改内部值(模板中会自动解包 ,无需写 .value)。

    示例:

    复制代码
    import { ref } from 'vue'
    const count = ref(0) // 包装基本类型
    console.log(count.value) // 必须加 .value → 0
    count.value++ // 修改值 → 响应式更新
    
    const user = ref({ name: 'Bob' }) // 包装对象类型(内部转 reactive)
    console.log(user.value.name) // 先 .value 拿到代理对象 → "Bob"
    user.value.age = 21 // 修改属性 → 响应式更新

3. 赋值行为:能否直接替换整个数据

  • reactive() :不能直接替换整个对象(会丢失响应式)。

    因为 reactive()返回的是原对象的 Proxy 代理 ,若直接赋值新对象(如 state = { ... }),新对象未被 Proxy 包裹,不再是响应式的。

    错误示例:

    复制代码
    const state = reactive({ count: 0 })
    state = { count: 1 } // ❌ 错误:直接替换对象,失去响应式
  • ref() :可以直接修改 .value(无论基本类型还是对象类型)。

    因为 ref()的 .value是可变的容器,替换 .value会触发响应式更新。

    正确示例:

    复制代码
    const count = ref(0)
    count.value = 1 // ✅ 正确:修改 .value → 响应式更新
    
    const user = ref({ name: 'Tom' })
    user.value = { name: 'Jerry' } // ✅ 正确:替换整个对象 → 响应式更新

4. 适用场景:如何选择?

场景 推荐 API 原因
处理基本类型(数字、字符串、布尔) ref() reactive()无法处理基本类型,必须用 ref()包装。
处理单值对象(如一个配置项) ref() 方便通过 .value整体替换,避免 reactive()的赋值陷阱。
处理复杂对象/数组(多属性、嵌套结构) reactive() 直接访问属性更简洁,无需 .value。
需要统一响应式逻辑(全用一种 API) ref() 所有类型都能用 ref()包装(对象类型内部转 reactive),风格一致。

5. 模板中的使用差异

  • reactive():直接在模板中使用代理对象的属性(无需额外处理)。

    示例:

    复制代码
    <template>
      <div>{{ user.name }} ({{ user.age }})</div>
    </template>
    <script setup>
    import { reactive } from 'vue'
    const user = reactive({ name: 'Alice', age: 20 })
    </script>
  • ref() :模板中自动解包 (无需写 .value),直接用变量名访问。

    示例:

    复制代码
    <template>
      <div>{{ count }}</div> <!-- 自动解包 count.value -->
      <div>{{ user.name }}</div> <!-- 自动解包 user.value.name -->
    </template>
    <script setup>
    import { ref } from 'vue'
    const count = ref(0)
    const user = ref({ name: 'Bob' })
    </script>

补充:toRefs()与 reactive()的配合

当需要将 reactive()对象的属性解构 到组件中时(避免失去响应式),可以用 toRefs()将每个属性转为 ref:

复制代码
import { reactive, toRefs } from 'vue'
const state = reactive({ count: 0, name: 'Alice' })
const { count, name } = toRefs(state) // 转为 ref 对象
console.log(count.value) // 0(需用 .value 访问)

总结:一句话区分

  • reactive():给对象/数组穿件「响应式外套」,直接摸属性;

  • ref():给任何数据装个「响应式盒子」 ,开盒子用 .value(模板里自动开)。

如果是新手,建议优先用 ref() (处理所有类型,避免踩坑);若明确处理复杂对象,用 reactive()更简洁。两者可以混合使用,核心是理解它们的响应式边界~

惠州大亚湾

相关推荐
Flynt30 分钟前
我把热榜那篇"禁用 axios"逐条实测了一遍:结论大体对,坑在它没讲的地方
前端·javascript·axios
Csvn1 小时前
bundle优化
前端
slongzhang_2 小时前
linux 递归删除源码文件|递归删除目录下 *.js,但排除 *.min.js
linux·开发语言·javascript
北冥有鱼2 小时前
发版后动态路由点击报 `Failed to fetch dynamically imported module`」问题上的完整排查与修复过程
前端·vue.js
静默回滚2 小时前
视频压到 25 MB 以内,码率要算、音轨要扣、余量要留
前端
用户37203749260182 小时前
把 10MB 中文语义模型塞进浏览器:STSB 做到教师模型的 93%,但线上 top1 只有 42%
前端
光锥智能2 小时前
海康机器人举行2026移动机器人新品发布会:箱式存拣升级,「明智」系列发布
java·前端·机器人
计算机魔术师2 小时前
Anthropic 上市文件最吓人的一幕,不是亏损 807 亿
前端
alsmile2 小时前
AI友好的可视化图形引擎自我革命:Meta2d.js 2.0 历时一年全新重写,性能与多人协作全面升级
前端·开源·数据可视化
行思理2 小时前
Nginx 跨站请求(CORS)配置完全指南:从原理到生产实践
java·前端·nginx