Skip to content

vue3 中 ref 和 reactive 有什么区别?

参考答案:

在 Vue 3 中,refreactive 都是用于创建响应式数据的核心 API,但它们在用途、返回值、适用场景和底层机制上存在明显差异。理解这两者的区别,有助于合理选择响应式策略、避免不必要的副作用,也有助于提升开发效率与代码一致性。

一、基本用途与语法对比

ref

  • 用于 包裹一个基本类型或对象,返回一个响应式对象,其值通过 .value 访问。
  • 适合处理单个值或希望显式管理响应式引用的场景。
ts
import { ref } from 'vue';

const count = ref(0);
count.value++; // 必须通过 .value 访问

reactive

  • 用于 将整个对象转换为响应式对象,直接访问属性即可触发响应式更新。
  • 更适合处理结构化的数据(对象、数组、嵌套结构等)。
ts
import { reactive } from 'vue';

const state = reactive({ count: 0 });
state.count++; // 直接访问属性即可

二、响应式行为差异

1. 响应式深度

  • ref:对基本类型做响应式包裹;对对象是浅层包裹,内部对象不会自动递归为响应式。

    ts
    const obj = ref({ a: 1 });
    obj.value.a = 2; // a 是响应式的,因为 Vue 内部自动转为 reactive
  • reactive:会将对象的所有嵌套属性递归转换为响应式(深层响应式)。

    ts
    const obj = reactive({ a: { b: 1 } });
    obj.a.b = 2; // b 是响应式的

2. 访问方式

  • ref:需要 .value 访问包裹的内容;
  • reactive:可直接访问属性。

不过在模板中(<template>),Vue 会自动解包 ref,所以不需要加 .value

三、在对象解构时的行为

  • ref 会失去响应性:

    ts
    const count = ref(0);
    const { value } = count;
    // value 是普通值,响应性丢失
  • reactive 直接解构会丢失响应性,推荐使用 toRefs 保留响应性

    ts
    const state = reactive({ count: 0 });
    const { count } = toRefs(state); // count 变为 ref

四、典型使用场景对比

场景使用建议原因或说明
基本类型的响应式值(数值、布尔等)使用 ref轻量、语义清晰
对象、数组、结构化数据使用 reactive自动深层响应式,写法简洁
对象属性需要解构出来使用配合 toRefs避免响应性丢失
在组合式 API 中管理局部状态两者都可视具体数据结构选择
定义类或工厂中需显式包装状态使用 ref更适合封装为单个引用

五、底层实现差异

  • ref 是对值的响应式容器封装,内部通过 Object.defineProperty 定义 .value,并调用 reactive 对对象自动包裹;
  • reactive 则是直接对目标对象进行 Proxy 包裹,返回一个代理对象,重写 get / set 等操作符;
  • 两者都基于 Vue 3 的响应式系统(effect, track, trigger),但入口形式和封装语义不同。

题目要点:

  • ref 更适合基本类型或希望明确响应式边界的场景,需要通过 .value 访问;
  • reactive 适用于复杂对象,具备深层响应式能力;
  • 解构响应式对象时注意响应性丢失问题,推荐配合 toRefs 使用;
  • 模板中 Vue 会自动解包 ref,但在 JS 中仍需显式 .value
  • 理解两者底层差异有助于组合式 API 的灵活使用和封装。