v-once 是静态节点的硬性冻结,v-memo 是带条件的子树记忆化;前者编译时提升为常量 vnode 并彻底跳过后续所有更新流程,后者运行时浅比较依赖数组决定是否跳过 diff 和 patch。

v-once 和 v-memo 都是 Vue 在运行时跳过不必要的 DOM 更新的指令,但它们的触发条件、适用边界和底层机制有本质区别。理解它们不是为了堆砌语法,而是为了在真实渲染路径中精准“减负”。
v-once:静态内容的硬性冻结
它不是缓存,而是标记。Vue 编译器在生成渲染函数时,会把带 v-once 的节点识别为“静态节点”,并将其提升到函数作用域顶层,作为常量 vnode 存储。后续所有更新周期中,patch 过程直接复用这个 vnode,完全绕过:
- 响应式依赖追踪(不收集 effect)
- 虚拟节点 diff 对比(不进入 patchElement 流程)
- 真实 DOM 操作(不调用 insert、remove 或 setAttribute)
这意味着子组件、插槽、计算属性、甚至 {{ }} 中的函数调用,都只执行一次。适合页脚版权、协议文本、初始化配置展示等真正永不变化的内容。
v-memo:带条件的子树记忆化
v-memo 是运行时决策,依赖数组决定是否跳过 patch。它的核心在于“记忆上次渲染的 vnode 子树 + 比较当前依赖值”。每次更新前,Vue 会浅比较传入的数组(如 v-memo="[id, status]")与上一次缓存的值:
- 全部相等 → 跳过该子树的 diff 和 patch,直接复用旧 vnode
- 任一不等 → 正常走完整渲染流程,同时更新缓存数组
它不阻止响应式追踪,也不影响子组件内部逻辑,只控制“是否重渲染这一段结构”。特别适合表格行、列表项、折叠面板等内容高频更新但局部稳定的情况。
关键区别与误用提醒
v-once 是“一次性快照”,v-memo 是“条件性缓存”。两者不能混用在同一元素上,且都要求依赖项必须是稳定、可比的值(避免用对象引用或未定义值):
- 不要对动态 key 使用 v-once,否则 key 变化时仍无法更新
- v-memo 的依赖数组长度必须固定,且每个位置语义明确(比如用 item.id 而非 item)
- v-memo="[]" 等价于 v-once,但语义不同:前者强调“无依赖”,后者强调“永不变”
- 二者都不解决首次渲染慢的问题,只优化后续更新开销

















