Vue3 的响应式系统源码级 shallowRef 与 shallowReactive 的实现原理与适用场景
字数 897 2025-11-19 18:51:11

Vue3 的响应式系统源码级 shallowRef 与 shallowReactive 的实现原理与适用场景

描述
shallowRef 与 shallowReactive 是 Vue3 响应式系统中用于"浅层"响应式的 API。它们与 ref 和 reactive 的核心区别在于:shallowRef 的 .value 属性不会被深度响应式化,shallowReactive 只会对对象的直接属性进行响应式处理,嵌套对象保持原始状态。

实现原理

  1. shallowReactive 实现机制

    • 创建时通过 createReactiveObject(target, true, shallowReactiveHandlers, ...) 传入 shallow 标志
    • 在 baseHandlers 中,对 GET 操作:如果读取的是对象类型值且非 shallow 模式,才递归调用 reactive
    • shallowReactiveHandlers 会设置 shallow=true,阻止嵌套对象的响应式转换
    // 简化的 shallowReactive 实现
    function shallowReactive(target) {
      return createReactiveObject(target, true, shallowHandlers)
    }
    
    const shallowHandlers = {
      get(target, key, receiver) {
        // 标记为浅层响应式
        if (key === '__v_isShallow') return true
    
        const res = Reflect.get(target, key, receiver)
        // 关键区别:不进行深度响应式转换
        track(target, 'get', key)
        return res // 直接返回原始值,不递归响应式化
      },
      set(target, key, value, receiver) {
        const oldValue = target[key]
        const result = Reflect.set(target, key, value, receiver)
        if (hasChanged(value, oldValue)) {
          trigger(target, 'set', key, value, oldValue)
        }
        return result
      }
    }
    
  2. shallowRef 实现机制

    • 内部通过 _shallow = true 标记区分普通 ref
    • 在设置 .value 时,如果是对象且非 shallow 模式,才转换为 reactive
    • 核心区别:shallowRef 的 .value 不会被自动深度响应式化
    class ShallowRefImpl {
      constructor(value, _shallow = true) {
        this._shallow = _shallow
        this._value = _shallow ? value : toReactive(value)
        this.dep = undefined
      }
    
      get value() {
        trackRefValue(this)
        return this._value // 直接返回,不进行深度转换
      }
    
      set value(newVal) {
        if (hasChanged(newVal, this._rawValue)) {
          this._value = this._shallow ? newVal : toReactive(newVal)
          triggerRefValue(this)
        }
      }
    }
    

适用场景

  1. 性能优化:当明确知道只需要监听顶层数据变化时,避免不必要的深度响应式转换开销
  2. 第三方库集成:集成不可变数据流库或需要保持对象身份的场景
  3. 大型对象处理:处理大型列表或复杂嵌套结构时,只关心顶层引用变化
  4. 组件 props:父组件传递大型对象给子组件,只需监听整个对象的替换

深度对比

  • reactive:深度响应式,嵌套对象会被递归转换
  • shallowReactive:浅层响应式,只监听直接属性变化
  • ref:自动对 .value 进行深度响应式转换
  • shallowRef:.value 保持原始状态,不进行深度转换

这种分层设计让开发者能够根据具体场景选择最合适的响应式粒度,在性能和控制力之间取得平衡。

Vue3 的响应式系统源码级 shallowRef 与 shallowReactive 的实现原理与适用场景 描述 shallowRef 与 shallowReactive 是 Vue3 响应式系统中用于"浅层"响应式的 API。它们与 ref 和 reactive 的核心区别在于:shallowRef 的 .value 属性不会被深度响应式化,shallowReactive 只会对对象的直接属性进行响应式处理,嵌套对象保持原始状态。 实现原理 shallowReactive 实现机制 创建时通过 createReactiveObject(target, true, shallowReactiveHandlers, ...) 传入 shallow 标志 在 baseHandlers 中,对 GET 操作:如果读取的是对象类型值且非 shallow 模式,才递归调用 reactive shallowReactiveHandlers 会设置 shallow=true,阻止嵌套对象的响应式转换 shallowRef 实现机制 内部通过 _shallow = true 标记区分普通 ref 在设置 .value 时,如果是对象且非 shallow 模式,才转换为 reactive 核心区别:shallowRef 的 .value 不会被自动深度响应式化 适用场景 性能优化 :当明确知道只需要监听顶层数据变化时,避免不必要的深度响应式转换开销 第三方库集成 :集成不可变数据流库或需要保持对象身份的场景 大型对象处理 :处理大型列表或复杂嵌套结构时,只关心顶层引用变化 组件 props :父组件传递大型对象给子组件,只需监听整个对象的替换 深度对比 reactive:深度响应式,嵌套对象会被递归转换 shallowReactive:浅层响应式,只监听直接属性变化 ref:自动对 .value 进行深度响应式转换 shallowRef:.value 保持原始状态,不进行深度转换 这种分层设计让开发者能够根据具体场景选择最合适的响应式粒度,在性能和控制力之间取得平衡。