问问你:vue3中ref和reactive的底层实现逻辑一样吗?

1. ref的底层实现

ref的核心作用是将一个值(尤其是基本类型值)包装成一个响应式对象,并通过.value属性访问和修改。它的实现依赖于RefImpl类,并通过tracktrigger机制实现依赖收集和更新触发。

源码分析

kotlin 复制代码
class RefImpl<T> {
  private _value: T
  public readonly __v_isRef = true

  constructor(private _rawValue: T, public readonly _shallow = false) {
    // 将原始值转换为响应式值
    this._value = _shallow ? _rawValue : convert(_rawValue)
  }

  get value() {
    // 依赖收集
    track(toRaw(this), TrackOpTypes.GET, 'value')
    return this._value
  }

  set value(newVal) {
    // 检查值是否发生变化
    if (hasChanged(toRaw(newVal), this._rawValue)) {
      this._rawValue = newVal
      // 更新值并转换为响应式
      this._value = this._shallow ? newVal : convert(newVal)
      // 触发更新
      trigger(toRaw(this), TriggerOpTypes.SET, 'value', newVal)
    }
  }
}

function ref(value) {
  return createRef(value)
}

function createRef(rawValue, shallow = false) {
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}

关键点分析

  • RefImplref的核心实现类,通过getset访问器拦截对.value的访问和修改。
    • get:在访问.value时,调用track进行依赖收集。
    • set:在修改.value时,调用trigger触发更新。
  • convert函数 :将原始值转换为响应式值。如果原始值是对象,则调用reactive将其转换为响应式对象。
  • tracktrigger:Vue 3的响应式系统的核心机制,分别用于依赖收集和更新触发。

设计思想

ref的设计是为了解决基本类型值的响应式问题。由于JavaScript的Proxy无法直接代理基本类型值(如numberstring等),ref通过将值包装在对象中,实现了对基本类型值的响应式支持。

2. reactive的底层实现

reactive的核心作用是创建一个响应式对象,它通过Proxy代理对象的属性访问和修改,从而实现对整个对象的响应式处理。

源码分析

javascript 复制代码
function reactive(target) {
  if (target && target.__v_isReadonly) {
    return target
  }
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers
  )
}

function createReactiveObject(
  target,
  isReadonly,
  baseHandlers,
  collectionHandlers
) {
  if (!isObject(target)) {
    return target
  }
  // 创建Proxy代理
  const proxy = new Proxy(target, baseHandlers)
  return proxy
}

关键点分析

  • Proxy代理reactive通过Proxy代理目标对象,拦截对对象属性的访问和修改。
    • get:在访问属性时,调用track进行依赖收集。
    • set:在修改属性时,调用trigger触发更新。
  • mutableHandlersProxy的处理器对象,定义了getsetdeleteProperty等拦截器。
  • createReactiveObject函数 :负责创建Proxy代理对象,并处理边界情况(如只读对象、非对象值等)。

设计思想

reactive的设计是为了处理复杂对象的响应式问题。它通过Proxy代理对象的属性,实现了对整个对象的深度响应式支持。与ref相比,reactive更适合处理复杂数据结构(如对象、数组等)。

3. ref和reactive的区别

4. 总结

  • ref :通过RefImpl类将值包装为响应式对象,适合处理基本类型值或单一对象的响应式需求。
  • reactive :通过Proxy代理整个对象,适合处理复杂对象的响应式需求。

在实际开发中,refreactive可以结合使用。例如,可以将一个对象的某个属性用ref包装,而将整个对象用reactive处理。理解它们的底层实现和设计思想,有助于更好地选择和使用这两种响应式工具。

5. 后续

下一篇咱们分析一下tracktrigger 的实现逻辑,刨根问底才是真!

相关推荐
郑州光合科技余经理1 小时前
本地生活系统:多业务订单字段怎么分账本导出
java·开发语言·前端·数据库·uni-app·php·ai编程
怕浪猫8 小时前
FDE 如何正确解决现场项目工程性的问题
前端·后端·ai编程
西瓜太郎12348 小时前
外层模型卡片与分组详情成功率不一致,应该怎么排查?
前端·typescript·go·软件工程·react
GreenTea9 小时前
vLLM 与 SGLang KV Cache 底层实现机制深度调研报告
前端·后端·算法
毕业设计70311 小时前
(免费领源码) 基于微信小程序的预制菜商城的设计与实现25172-java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
vue.js·python·mysql·微信小程序·pycharm·微信开发者工具·推荐算法
xifangge202511 小时前
AGENTS.md 怎么写?涵盖 Java、Python、Vue、Go 的 8 套开箱即用模板
java·vue.js·python
几何心凉11 小时前
没有万能模型:我用 AiiOnly Token Plan,把多款大模型的长处拼进同一个项目
前端
kyriewen12 小时前
Claude Code 的额度今天缩水了17%——官方公告上写的是"永久提高25%"
前端·ai编程·claude
雪芽蓝域zzs12 小时前
vue解构平铺VS对象包裹
前端·javascript·vue.js
风骏时光牛马13 小时前
从零到实战,完整AI学习路线
前端