Vue 3 响应式优化核心是避免不必要的深层代理:用 shallowReactive/shallowRef 控制代理深度;扁平化嵌套结构并用 ID 映射;通过 computed 提前解析长路径;对惰性结构按需激活 reactive。

深层嵌套对象会触发 Vue 3 响应式系统递归代理每一层属性,造成大量 Proxy 初始化、依赖收集和更新通知开销。优化核心是:**不让不需要响应的部分进入响应式系统**。
用 shallowReactive 或 shallowRef 控制代理深度
当嵌套结构整体作为“不可变单元”使用(如 API 快照、配置项、表格原始数据),不需监听内部字段变化时:
- shallowReactive(obj):只代理第一层属性,子对象保持普通对象形态。适合需局部更新顶层字段但忽略深层变化的场景
-
shallowRef(obj):仅
.value整体响应,内部完全不转响应式。适合读多写少、整块替换的数据源,内存占用可降 40%+
例如:const tableData = shallowRef(await api.list()),后续切换页码直接 tableData.value = nextPage,跳过数千字段的 Proxy 初始化。
扁平化结构 + ID 映射替代深层嵌套
避免在 state 中存类似 { users: { u1: { profile: { address: { city: '' } } } } } 这类结构:
- 拆成独立状态片:
users: []、profiles: {}、addresses: {} - 用 ID 字段关联,如
user.profileId指向profiles[profileId] - 组件按需组合,只订阅自己关心的 ID 对应片段,缩小响应式依赖范围
用 computed / getter 提前解析长路径
模板中反复访问 state.user.profile.address.city 会多次触发多层 Proxy getter,且无法缓存:
- 在 store 中定义派生属性:
cityName() { return this.user?.profile?.address?.city || '' } - 组件直接绑定
cityName,而非原始嵌套路径 - 对静态中间结构(如地址对象)可配合
Object.freeze,彻底跳过响应式转换
懒代理:按需激活深层响应
对“多数时间收起、偶尔展开”的结构(如树形菜单、折叠面板):
- 初始只对顶层节点用
reactive,子节点暂存为普通对象 - 用户点击展开时,再用
reactive包裹对应子节点,触发响应式升级 - 避免为未使用的深层节点提前承担代理开销



















