当前位置: 首页 > article >正文

Vue3中ref与reactive的区别

在 Vue 3 中,refreactive 是两种不同的响应式数据创建方式,它们的区别和实现方式如下:


一、核心区别

特性refreactive
适用类型基本类型 + 对象类型仅对象类型(对象/数组/Map/Set)
访问方式通过 .value 访问直接访问属性
解构响应性需要 toRefs 保持解构后的响应性直接解构会丢失响应性
深层响应性自动递归代理嵌套对象自动递归代理嵌套对象
模板自动解包支持(模板中无需 .value直接访问属性

二、实现方式

1. ref 的实现
  • 核心机制:通过一个对象包装值(RefImpl 类),利用 getter/setter + Proxy 实现响应式。

  • 源码关键点

class RefImpl<T> {
   private _value: T
 private _rawValue: T // 原始值(避免对象被 reactive 二次代理)
   
   constructor(value: T) {
     this._rawValue = value
     this._value = isObject(value) ? reactive(value) : value
   }
   
   get value() {
     track(this, TrackOpTypes.GET, 'value') // 依赖收集
     return this._value
   }
   
   set value(newVal) {
     if (hasChanged(newVal, this._rawValue)) {
       this._rawValue = newVal
       this._value = isObject(newVal) ? reactive(newVal) : newVal
       trigger(this, TriggerOpTypes.SET, 'value') // 触发更新
     }
   }
 }
  • 特点

    • 对基本类型直接通过 getter/setter 监听。
    • 对对象类型内部使用 reactive 代理。
2. reactive 的实现
  • 核心机制:基于 Proxy 代理对象,拦截 get/set/deleteProperty 等操作。

  • 源码关键点

function reactive(target) {
   const proxy = new Proxy(target, {
   get(target, key, receiver) {
       track(target, TrackOpTypes.GET, key) // 依赖收集
       const res = Reflect.get(target, key, receiver)
       return isObject(res) ? reactive(res) : res // 递归代理嵌套对象
     },
     set(target, key, value, receiver) {
       const oldValue = target[key]
       const result = Reflect.set(target, key, value, receiver)
       if (hasChanged(value, oldValue)) {
         trigger(target, TriggerOpTypes.SET, key) // 触发更新
       }
       return result
     }
   })
   return proxy
 }
  • 特点

    • 通过 Proxy 实现深层响应式。
    • 递归代理嵌套对象(性能优化可通过 shallowReactive 避免)。

三、使用场景

1. 使用 ref 的场景
  • 需要响应式的基本类型值(如 string/number/boolean)。
  • 需要显式控制值的引用(如需要重新赋值整个对象时)。
  • 需要兼容模板自动解包(模板中无需 .value)。
2. 使用 reactive 的场景
  • 需要响应式的复杂对象或数组。
  • 需要保持对象引用不变,仅修改属性。
  • 需要深层响应式(如嵌套对象自动代理)。

四、最佳实践

  1. 优先选择 ref
    对于基本类型或需要频繁重新赋值的对象,使用 ref 更直观。

  2. 复杂对象用 reactive
    当需要处理嵌套结构且不需要重新赋值整个对象时,reactive 更简洁。

  3. 解构时用 toRefs
    解构 reactive 对象时,使用 toRefs 保持响应性:

const state = reactive({ count: 0 })
 const { count } = toRefs(state) // 解构后仍为 Ref 类型

五、底层原理对比

机制refreactive
依赖收集通过 getter 中的 track通过 Proxy.get 中的 track
触发更新通过 setter 中的 trigger通过 Proxy.set 中的 trigger
性能开销基本类型更低,对象类型与 reactive 相同对象类型高效,嵌套对象递归代理

总结

  • ref:更通用的响应式工具,通过 .value 访问,适合基本类型或需要重新赋值的对象。
  • reactive:专为对象设计的响应式工具,适合深层嵌套结构,直接访问属性更简洁。
  • 实现差异ref 通过 RefImpl 类包装值,reactive 通过 Proxy 代理对象。

http://www.kler.cn/a/560547.html

相关文章:

  • Java基础进阶提升
  • TCP半连接、长连接
  • 什么是 Cloud Studio DeepSeek ; 怎么实现Open WebUI快速体验
  • 【游戏——BFS+分层图】
  • CNN 卷积神经网络
  • 2016年下半年试题二:论软件设计模式及其应用
  • Java 进阶面试指南
  • 【7days-golang/gee-web/day02】设计Context-学习笔记
  • 前端学习—HTML
  • 九九乘法表 matlab
  • JPA与存储过程的完美结合
  • Unity Mirror 从入门到入神(一)
  • Java Set实现类面试题
  • 【linux】文件与目录命令 - awk
  • PHP MySQL 创建数据库
  • 机器学习数学通关指南——微分中值定理和积分中值定理
  • 塔能物联运维助力智慧隧道安全升级——城市交通保障新力量
  • std::thread的同步机制
  • 计算机视觉算法实战——跌倒检测(主页有源码)
  • 山东大学软件学院nosql实验三