Vue3 的响应式系统源码级 shallowRef 与 shallowReactive 的实现原理与适用场景
字数 897 2025-11-19 18:51:11
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,阻止嵌套对象的响应式转换
// 简化的 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 } } - 创建时通过
-
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) } } } - 内部通过
适用场景
- 性能优化:当明确知道只需要监听顶层数据变化时,避免不必要的深度响应式转换开销
- 第三方库集成:集成不可变数据流库或需要保持对象身份的场景
- 大型对象处理:处理大型列表或复杂嵌套结构时,只关心顶层引用变化
- 组件 props:父组件传递大型对象给子组件,只需监听整个对象的替换
深度对比
- reactive:深度响应式,嵌套对象会被递归转换
- shallowReactive:浅层响应式,只监听直接属性变化
- ref:自动对 .value 进行深度响应式转换
- shallowRef:.value 保持原始状态,不进行深度转换
这种分层设计让开发者能够根据具体场景选择最合适的响应式粒度,在性能和控制力之间取得平衡。