shallowreactive和shallowref通过仅代理第一层属性来提升性能,适用于大型静态数据、第三方库实例集成、只读嵌套信息及需手动控制更新时机的场景。

它们能提升性能的核心场景,是当你面对大型或深层嵌套数据,但实际只依赖顶层变动时。Vue 默认的 reactive 和 ref 会递归遍历整个对象树,把每一层都转成响应式代理——这在数据量大时会明显拖慢初始化、内存占用和后续更新效率。而 shallowReactive 和 shallowRef 跳过深层处理,只盯住第一层,自然就省下大量开销。
处理超大静态数据(如图表、列表、富文本内容)
这类数据通常一次性加载、整体替换,内部字段极少甚至从不单独修改。
- 用
shallowRef存储:比如一个含 5 万条坐标的地图瓦片数据对象,你只会在切换区域时chartData.value = newData整体赋值,从不改chartData.value.points[100].x—— 这时用shallowRef避免对 5 万个点做响应式代理,初始化快、内存少 - 用
shallowReactive管理结构:比如一个仪表盘状态对象{ title: '销售额', data: hugeArray, config: { theme: 'dark' } },你只改state.title或state.data整体替换,不碰state.config.theme的响应性 —— 用shallowReactive就不会去代理hugeArray和config内部
集成第三方库实例(如 ECharts、Mapbox、Monaco 编辑器)
这些库内部会直接修改传入的对象,且你并不需要 Vue 监听它们的内部变化。
-
shallowRef适合存实例引用:例如const chart = shallowRef(null),挂载后赋值chart.value = echarts.init(dom);之后你只关心“有没有这个实例”,不监听chart.value.option是否变 —— 避免 Vue 对整个 ECharts 实例对象做响应式劫持,防止冲突和性能损耗 -
shallowReactive适合传配置对象:比如把mapOptions传给 Mapbox,你只希望mapOptions.center变了触发重设,但不想让mapOptions.style.layers里几百个图层配置被深度代理 —— 用shallowReactive刚好控制粒度
避免无意义的深层监听(如仅展示的嵌套信息)
有些数据纯用于渲染,业务逻辑中从不修改其内部属性,却因深度响应式白白消耗资源。
- 用户资料卡片:
const profile = shallowReactive({ name: 'Alice', contact: { email: 'a@b.c', phone: '123' } })。模板里只读{{ profile.name }}和{{ profile.contact.email }},但contact永远不变 —— 此时shallowReactive不代理contact,访问更快,且不会为email建立依赖追踪 - 表单初始值缓存:
const initForm = shallowRef({ user: { id: 1 }, meta: { createdAt: '2024-01-01' } })。你只在重置时form.value = { ...initForm.value },从不改initForm.value.user.id—— 完全没必要让它可响应
需要手动控制更新时机的场景
当深层修改确实会发生,但你希望明确决定何时通知视图更新,而不是每次赋值都触发。
- 用
shallowRef+triggerRef:比如一个编辑器内容对象,你在输入过程中频繁修改doc.value.blocks数组,但只想在“完成编辑”时统一刷新界面 —— 改完调一次triggerRef(doc)即可,避免中间几十次无意义 rerender - 用
shallowReactive+ 顶层赋值:比如一个配置对象,你批量修改了state.nested.a、state.nested.b、state.nested.c,最后再state.nested = { a, b, c }触发一次更新,比三次独立响应更可控











