vue3中的ref与reactive的原理,使用和区别

在 Vue 3 中,ref 和 reactive 是实现响应式数据的核心 API,它们基于 Proxy 实现,但适用场景和使用方式有所不同。以下从原理、使用方法和核心区别三个方面详细说明:

一、原理:基于 Proxy 的响应式实现

Vue 3 的响应式系统通过 ES6 Proxy 实现,相比 Vue 2 的 Object.defineProperty,Proxy 能拦截对象的所有操作(如新增属性、删除属性、数组索引修改等),天然支持更全面的响应式场景。

  • reactive 直接对对象 / 数组创建 Proxy 代理,拦截其读写操作。
  • ref 则是对基本类型(如 Number、String)或复杂类型进行包装,内部通过一个包含 value 属性的对象实现响应式,本质上也是基于 Proxy。

二、使用方法

1. reactive:处理对象 / 数组类型

作用:将对象或数组转为响应式数据,直接操作原对象的属性即可触发更新。注意

  • 只能传入对象或数组,传入基本类型(如 reactive(123))会报警告且不生效。
  • 不能直接替换整个对象,否则会丢失响应式:
    // 错误:替换后 user 不再是响应式对象
    user = reactive({ name: '李四' }); 
    
2. ref:处理基本类型或复杂类型

作用:将基本类型(Number、String、Boolean 等)或复杂类型转为响应式数据,通过 .value 访问和修改值。

import { ref } from 'vue';

// 基本类型
const count = ref(0);
const message = ref('Hello');

// 复杂类型(对象/数组也可以用 ref)
const user = ref({ name: '张三' });
const list = ref([1, 2, 3]);

// 修改值(必须通过 .value)
count.value++; // 视图会更新
message.value = 'World'; // 视图会更新

// 修改复杂类型的属性(两种方式均可)
user.value.age = 20; // 方式1:通过 .value 访问对象
list.value.push(4);  // 方式1:通过 .value 访问数组

// 注意:替换整个复杂类型时,响应式仍保留
user.value = { name: '李四' }; // 有效,仍为响应式

注意

  • 在 模板中使用 ref 时,Vue 会自动解包(无需写 .value
    <template>
      <p>{{ count }}</p> <!-- 直接用 count,无需 count.value -->
    </template>
    
  • 在 setup 函数或组合式 API 中,必须通过 .value 访问

三、核心区别

维度reactiveref
处理类型仅支持对象 / 数组支持基本类型(number/string 等)和复杂类型
访问方式直接访问属性(如 user.name需通过 .value 访问(模板中自动解包)
替换数据不能直接替换整个对象(会丢失响应式)可直接替换 .value(响应式保留)
解构赋值解构后会丢失响应式(需用 toRefs解构时需保留 .value 才能维持响应式
适用场景复杂对象 / 数组的响应式管理基本类型、单个值的响应式管理,或需要频繁替换的复杂类型
关键差异解析:
  1. 类型支持

    • reactive 只能处理对象 / 数组,这是最核心的限制;
    • ref 无类型限制,万能但对对象 / 数组本质是包装成 { value: 对象 }
  2. 访问方式

    • reactive 操作直观(直接点语法),但面对基本类型无能为力;
    • ref 需用 .value,稍显繁琐,但统一了所有类型的响应式处理方式。
  3. 解构与响应式保留

    • 对 reactive 对象解构时,属性会失去响应式,需用 toRefs 转换:
      import { reactive, toRefs } from 'vue';
      const user = reactive({ name: '张三', age: 20 });
      const { name, age } = toRefs(user); // 解构后仍为响应式(ref 类型)
      
    • 对 ref 解构时,直接解构会丢失响应式,需保留 .value 或用 toRef
      const count = ref(0);
      const { value: countVal } = count; // 需显式获取 .value
      

四、使用建议

  • 基本类型(如数字、字符串):优先用 refreactive 不支持)。
  • 简单对象 / 数组:若无需替换整个对象,用 reactive 更直观;若需要频繁替换(如重置数据),用 ref 更方便。
  • 复杂业务场景:推荐用 ref 统一管理,避免 reactive 的解构问题(尤其在组合式 API 中,ref 更易与 setup 函数的返回值配合)。

例如,在组件中:

// 推荐:用 ref 统一管理
const user = ref({ name: '张三' });
const age = ref(20);
const list = ref([1, 2, 3]);

// 后续可直接替换
user.value = { name: '李四' }; // 安全且简单

总结

reactive 和 ref 都是基于 Proxy 实现的响应式 API,核心区别在于:

  • reactive 面向对象 / 数组,操作直观但有类型限制;
  • ref 面向所有类型,通过 .value 访问,更灵活通用。

实际开发中,ref 因其普适性(支持所有类型)和灵活性(可直接替换值),使用频率往往更高,尤其是在 Vue 3 的组合式 API 中。

注:用于自己学习,查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值