shallowref 的核心价值是避免高频更新时的代理开销,仅响应整个行情快照的替换而非字段级变化,从而降低内存占用与 gc 压力。

在股票行情看板这类高频更新、数据量大、结构固定但内部字段极少需单独响应的场景中,shallowRef 的核心价值不是“让刷新更快”,而是“避免为每次刷新支付不必要的代理开销”。它把响应式监听从“每只股票的每个字段变化”收窄到“整个行情快照是否被整体替换”,从而大幅降低内存占用与 GC 压力,让页面更稳定、更扛压。
为什么默认 ref 在行情看板里容易拖垮性能
假设你用 ref([{ symbol: 'AAPL', price: 192.34, change: -0.21 }, ...]) 管理 500 只股票的实时数据:
- Vue 会对数组本身、每只股票对象、甚至 price/change 这类基础字段都创建 Proxy 和依赖追踪链
- 每秒推送 100 条更新(比如逐只刷新),Vue 需要反复触发 100 次细粒度依赖通知,中间还夹杂大量无效 diff(比如只改了 price,但 name、volume 等字段也参与比对)
- 内存中堆积大量 Proxy 实例和 dep 对象,V8 GC 频繁介入,滚动或切换 tab 时容易卡顿
shallowRef 的正确用法:只响应“快照替换”,不响应“字段修改”
行情数据本质是“整批覆盖”——后端推送新快照,前端直接替换整个数组,而不是逐个字段 patch。这正是 shallowRef 的理想场景:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 声明:
const quotes = shallowRef([])—— 仅监听.value引用是否被赋新值 - 接收新快照:
quotes.value = newQuoteArray✅ 触发视图更新(一次完整重绘) - 错误写法:
quotes.value[0].price = 192.55❌ 不触发更新(也不该这么做)
配合 triggerRef 实现“局部修正 + 批量刷新”
极少数情况需要微调单只股票(如人工标记自选股、临时屏蔽异常数据),又不想全量替换:
- 先直接修改:
quotes.value[0].isFavorite = true - 再手动触发:
triggerRef(quotes)✅ 通知 Vue 重新执行依赖它的渲染逻辑 - 优势:避免高频触发(比如每秒 10 次 triggerRef),可合并多次修改后统一触发,比深度响应式更可控
进阶搭配:markRaw + shallowRef 防止第三方污染
如果看板集成了 ECharts 或 Canvas 渲染器,且行情数据被传入图表实例作源数据:
- 不要把原始行情数组传给
reactive()或ref()后再塞进图表 - 改用:
const rawQuotes = markRaw(largeQuoteList); const quotes = shallowRef(rawQuotes) - 效果:Vue 完全跳过该数组的响应式转换,图表拿到的是纯 JS 数组,无 Proxy 干扰,初始化快、运行稳
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









