zzz 发表于 2025-7-18 16:01:50

ref和reactive底层原理的区别

本帖最后由 zzz 于 2025-7-18 16:12 编辑

ref和reactive都是构建响应式数据模型的两大核心工具,分别服务于不同的场景并具有独特的使用方式与底层实现机制。

数据类型支持
ref:支持基本类型(如字符串、数字、布尔值)和对象类型,内部会自动将对象类型转换为reactive实现响应式代理。
reactive:仅支持对象、数组、Map/Set等复杂类型,通过Proxy代理实现深度响应式追踪。

响应式实现机制
ref:通过封装对象的.value属性实现响应式,对基本类型使用Object.defineProperty劫持数据,对象类型则调用reactive转换为代理。
它的实现依赖于RefImpl类,并通过track和trigger机制 实现依赖收集和更新触发。//源码分析
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)
}
// RefImpl类:ref的核心实现类,通过get和set访问器拦截对.value的访问和修改。
//   get:在访问.value时,调用track进行依赖收集。
//   set:在修改.value时,调用trigger触发更新。
// convert函数:将原始值转换为响应式值。如果原始值是对象,则调用reactive将其转换为响应式对象。
// track和trigger:Vue 3的响应式系统的核心机制,分别用于依赖收集和更新触发。
reactive:Proxy拦截对象的增删改查操作,结合Reflect操作原始数据,实现深层响应式追踪。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触发更新。
// mutableHandlers:Proxy的处理器对象,定义了get、set、deleteProperty等拦截器。
// createReactiveObject函数:负责创建Proxy代理对象,并处理边界情况(如只读对象、非对象值等)。
适应场景
‌ref:适合简单数据、需跨组件传递的独立变量或需替换整个对象的场景。
‌reactive:适合复杂嵌套对象、数组或需深度响应式追踪的场景。

页: [1]
查看完整版本: ref和reactive底层原理的区别