Vue 3中的ref和reactive有什么区别

Vue 3中的ref和reactive有什么区别?这个问题对于刚开始学习Vue 3的人来说可能有点困惑,特别是这两个API都用于响应式数据的情况下。首先先回忆一下它们的用法和内部机制。

ref通常用于基本类型的数据,比如字符串、数字、布尔值,但也可以用于对象和数组。而reactive是专门用来处理对象类型(包括数组和对象)的响应式数据。

在 Vue 3 的 Composition API 中,refreactive 是两种常用的响应式数据声明方式,它们的区别主要体现在以下几个方面:

1. 适用数据类型

refreactive
适用类型基本类型 (stringnumberboolean),也可用于对象仅对象类型(对象、数组、Map、Set 等)
示例const count = ref(0)const state = reactive({ count: 0 })
  • ref 的灵活性: 虽然 ref 主要用于基本类型,但它可以包裹任意值(包括对象)。当包裹对象时,内部会调用 reactive 实现深层响应式。

 

2. 访问方式 

refreactive
访问方式需要通过 .value 访问直接访问属性
示例count.value++state.count++
// ref 示例
const count = ref(0);
console.log(count.value); // 0

// reactive 示例
const state = reactive({ count: 0 });
console.log(state.count); // 0
  • 为什么 ref 需要 .value? ref 通过将值包裹在一个对象中({ value: ... })实现响应式,因此需要 .value访问。这种设计使得基本类型也能通过引用传递保持响应性。

3. 解构时的响应性 

 

refreactive
解构响应性解构后仍保留响应性直接解构会丢失响应性

 

// reactive 解构问题
const state = reactive({ count: 0 });
const { count } = state; // 解构后 count 失去响应性!

// 使用 toRefs 解决
const state = reactive({ count: 0 });
const { count } = toRefs(state); // count 是 ref,保持响应性
count.value++; // 生效
  • reactive 的局限性: 直接解构 reactive 对象会失去响应性,需配合 toRefs 将属性转为 ref

4. 深层响应性 

refreactive
深层响应✅ 默认深层响应✅ 默认深层响应
// ref 包裹对象
const obj = ref({ a: { b: 1 } });
obj.value.a.b = 2; // 响应式更新

// reactive 包裹对象
const state = reactive({ a: { b: 1 } });
state.a.b = 2; // 响应式更新

 5. 实现原理

refreactive
实现方式通过 Object.defineProperty 监听 .value通过 Proxy 代理整个对象

ref 的底层

class RefImpl {
  constructor(value) {
    this._value = value;
    // 监听 .value 的变化
  }
}

 reactive 的底层

const proxy = new Proxy(target, {
  get(target, key) { /* 收集依赖 */ },
  set(target, key, value) { /* 触发更新 */ }
});

 

6. 使用场景

场景refreactive
基本类型✅ 推荐❌ 不推荐(需包裹成对象)
复杂对象✅ 可用(但更推荐 reactive✅ 推荐
逻辑复用✅ 适合返回独立值✅ 适合返回对象结构

总结表格

特性refreactive
数据类型任意类型对象类型
访问方式.value直接访问属性
解构响应性✅ 保持响应性❌ 需配合 toRefs
底层实现Object.definePropertyProxy
推荐场景基本类型、需要解构的独立值复杂对象、需要直接操作属性的场景

 

import { ref, reactive, toRefs } from 'vue';

// ref 示例
const count = ref(0);
const user = ref({ name: 'Alice', age: 25 });
user.value.age++; // 修改对象属性

// reactive 示例
const state = reactive({ 
  items: ['apple', 'banana'],
  config: { darkMode: true }
});
state.items.push('orange'); // 直接操作
const { config } = toRefs(state); // 解构保持响应性

最佳实践

  1. 优先使用 ref 处理基本类型(如数字、字符串)。
  2. 优先使用 reactive 处理复杂对象(如表单数据、配置对象)。
  3. 需要解构时,用 toRefs 包裹 reactive 对象。
  4. 组合逻辑复用时,返回 ref 或 reactive 取决于数据类型是否独立。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值