mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
543 字
1 分钟
Vue3-reactive
2026-04-08
无标签

reactive / shallowReactive / readonly / shallowReadonly


一、前置核心原理#

1. Vue3 响应式的唯一底层:ES6 Proxy(ECMAScript 2015 标准)#

官方源码:packages/reactivity/src/reactive.ts

new Proxy(target, {
get(target, key) { // 读取属性 → track 收集依赖
track(target, key)
return Reflect.get(target, key)
},
set(target, key, val) { // 修改属性 → trigger 触发更新
const result = Reflect.set(target, key, val)
trigger(target, key)
return result
}
})

官方铁律:#

  • Proxy 只能代理 对象/数组/函数
  • 不能代理 string/number/boolean/undefined/null

2. Vue3 所有响应式对象,都来自同一个创造函数:#

createReactiveObject(源码唯一入口)#

function createReactiveObject(
target: Target,
isReadonly: boolean,
baseHandlers: ProxyHandler<any>,
collectionHandlers: ProxyHandler<any>
) {
// 缓存,避免重复代理
const proxyMap = isReadonly ? readonlyMap : reactiveMap
const existingProxy = proxyMap.get(target)
if (existingProxy) return existingProxy
// 创建 Proxy
const proxy = new Proxy(target, baseHandlers)
proxyMap.set(target, proxy)
return proxy
}

四个 API 都是这个函数的不同参数!


二、reactive(深度响应式)#

官方定义#

返回一个深度响应式代理,嵌套对象会自动递归转为响应式

源码调用#

export function reactive(target: object) {
return createReactiveObject(
target,
false, // 不是只读
mutableHandlers, // 可读写的深层代理
mutableCollectionHandlers
)
}

底层原理(mutableHandlers)#

  • get:自动递归 reactive 子对象
  • get:track 收集依赖
  • set:trigger 触发更新
  • 深度监听所有层级

文章示例解释#

const person = reactive({
name: 'zs',
age: 18,
friend: { name: 'ls' }
})
person.name = 'ww' // 响应式
person.friend.name = 'zl' // 响应式(深度)

特点#

  • 深度递归代理
  • 读写正常
  • 嵌套对象自动变响应式

三、shallowReactive(浅响应式)#

官方定义#

只有第一层属性是响应式,深层对象不代理、不递归。

源码调用#

export function shallowReactive(target: object) {
return createReactiveObject(
target,
false,
shallowHandlers, // 关键:浅处理函数
shallowCollectionHandlers
)
}

底层原理(shallowHandlers)#

get 直接返回原值,不递归、不转为 reactive

get(target, key) {
return target[key] // 直接返回,不做深层代理
}

文章示例解释#

const person = shallowReactive({
name: 'zs',
friend: { name: 'ls' }
})
person.name = 'ww' // 触发更新(第一层)
person.friend.name = 'zl'// 不触发(深层不是Proxy)

作用#

性能优化:大数据列表、第三方对象、不希望深度监听的场景


四、readonly(深度只读)#

官方定义#

返回一个深度只读代理任何层级都不能修改,只能读

源码调用#

export function readonly(target: object) {
return createReactiveObject(
target,
true, // ✨ 只读
readonlyHandlers,
readonlyCollectionHandlers
)
}

底层原理(readonlyHandlers)#

  • get:正常收集依赖
  • set:抛出警告,不修改
  • deleteProperty:禁止删除
set() {
console.warn(`只读对象,不可修改`)
return true
}

文章示例解释#

const state = readonly({
name: 'zs',
friend: { name: 'ls' }
})
state.name = 'ww' // ❌ 警告
state.friend.name = 'zl' // ❌ 警告(深度只读)

官方用途#

  • props 就是 readonly
  • 配置、默认数据、禁止修改的状态

五、shallowReadonly(浅只读)#

官方定义#

只有第一层只读,深层可以修改,且不是响应式。

源码调用#

export function shallowReadonly(target: object) {
return createReactiveObject(
target,
true,
shallowReadonlyHandlers,
shallowReadonlyCollectionHandlers
)
}

底层原理#

  • 第一层:set 拦截 → 只读
  • 深层:直接返回原对象,不代理、可修改

文章示例解释#

const state = shallowReadonly({
name: 'zs',
friend: { name: 'ls' }
})
state.name = 'ww' // 禁止
state.friend.name = 'zl' // 允许修改

六、源码级核心区别#

Vue3 源码中,4 个API 只由 3 个维度控制

  1. isReadonly:是否只读
  2. isShallow:是否浅层
  3. deep:true/false:是否递归代理

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Vue3-reactive
https://www.choria.top/posts/vue3-reactive/
作者
乔瑞雅·克林威尔
发布于
2026-04-08
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录