v-once 和 v-memo 是 vue 3 中优化后续重渲染的指令:v-once 编译期标记静态节点,永久跳过更新;v-memo 运行时依依赖数组浅比较,按需跳过子树更新;二者分层配合可高效提升高频更新场景性能。

v-once 和 v-memo 是 Vue 3 中专为减少不必要重渲染而设的两个轻量指令,它们不加快首次渲染,只让后续更新更省力。用对地方,能明显缓解高频更新场景下的卡顿。
v-once:适合真正不变的内容
它不是缓存,而是编译期标记——Vue 会把带 v-once 的节点提升为常量 vnode,之后所有更新周期都直接复用,跳过响应式追踪、diff 对比和 DOM 操作。
- 适合页脚版权、协议文本、固定导航栏、初始化配置说明等整个生命周期都不变的内容
- 子组件、插槽、{{ }} 里的函数调用都只执行一次,之后彻底冻结
- 别给动态 key 加 v-once,否则 key 变了也刷不出来(节点已脱离响应式系统)
- 避免误用于“看起来不动但其实会变”的字段,比如某个状态字段只是暂时没改,不代表永远不变
v-memo:按需跳过子树更新
v-memo 是运行时行为,靠一个固定长度的依赖数组做浅比较。只有数组里每个值都和上次一样,才跳过该子树的 diff 和 patch;任一变化,就走完整流程并更新缓存。
- 适合表格行、消息列表、实时行情卡片等局部稳定、整体高频更新的区域
- 推荐语义化写法,比如 v-memo="[item.id, item.status]",而不是 v-memo="[item]"
- v-memo="[]" 功能上等价于 v-once,但语义不同:前者表示“无依赖需检查”,后者表示“永不变”
- 它不阻止子组件内部响应式逻辑,只是控制外层要不要重渲染这一块
搭配使用更高效
真实项目中,二者常分层配合。例如 shadcn-vue 的数据表格:
- 整个
和 用 v-once,因为结构完全静态 - 每行
用 v-memo="[row.id, row.updatedAt]",确保仅关键字段变化才更新整行 - 行内图标或状态标签若完全静态(如固定文字“已发布”),可在其内部再套一层 v-once
注意边界和陷阱
这两个指令不解决首次渲染慢的问题,只优化后续更新开销。使用前要确认:
- 依赖项必须是稳定、可比的基础类型(string/number/boolean),避免传对象引用或 undefined
- v-memo 的数组长度不能动态增减,否则浅比较失效,失去优化效果
- v-once 冻结的是整个 vnode 子树,如果其中混入本该响应 count 变化的按钮,就会出错
- v-once 和 v-memo 不能混用在同一元素上
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










