问问你: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 的实现逻辑,刨根问底才是真!

相关推荐
zhougl9962 小时前
html处理Base文件流
linux·前端·html
花花鱼2 小时前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_2 小时前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo3 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
杉之5 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端5 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡5 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木6 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!7 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷7 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript