v-once和v-memo是vue 3中用于跳过虚拟dom diff与patch的轻量优化指令:v-once在编译期标记静态节点并复用首次渲染结果;v-memo则在运行时依据依赖数组浅比较决定是否复用子树。

Vue.js 渲染性能瓶颈往往不是出在“写错代码”上,而是出现在虚拟 DOM 的更新逻辑没被正确引导时。关键不在于禁用什么功能,而在于让 Vue 知道哪些该重用、哪些该跳过、哪些根本不用动。
用 Vue DevTools 定位慢组件
打开 Vue DevTools 的 Components 面板,点击右上角的“Performance”按钮启用性能追踪。操作一次页面交互(比如点击按钮触发列表刷新),然后查看各组件的 Render Time 和 Update Count。重点关注那些渲染时间超过 20ms 或更新次数异常高的组件。
常见线索:
- 某个子组件每次父组件更新都重新 render,但内部数据其实没变 → 考虑加
shouldComponentUpdate类似逻辑(用v-memo或shallowRef+markRaw) - 一个列表组件渲染耗时陡增,且
key是:key="index"→ 改为稳定唯一 ID - 计算属性里访问了深层嵌套对象或调用了未缓存的方法 → 拆解依赖或用
computed缓存结果
检查虚拟 DOM Diff 是否失效
Vue 的 diff 默认只做同层级比对,一旦结构变动超出预期,就会退化为全量重建。典型表现是:列表顺序调整后,输入框失焦、滚动位置重置、动画中断。
确保以下三点:
-
列表必须用
:key,且 key 值稳定可追踪(不推荐v-for="(item, i) in list" :key="i") -
避免在 v-for 内部直接修改原始数组索引(如
list[0] = newItem),优先用splice、push、map等返回新引用的操作 -
动态组件切换时,加上
key强制区分不同实例(<component :is="currentView" :key="currentView"></component>)
识别并绕过不必要的 patch
不是所有节点都需要参与 diff。Vue 提供了几种轻量级跳过机制:
-
v-once:适合纯静态内容(如版权信息、说明文字),首次渲染后不再响应数据变化 -
v-memo(Vue 3.2+):按依赖数组控制是否跳过 patch,例如v-memo="[item.id, item.status]",只有这两个值都未变才跳过 - 将大型不可变对象标记为非响应式:
const staticData = markRaw(largeConfig),避免 proxy 代理开销
用 Performance 面板验证真实开销
Chrome DevTools 的 Performance 面板能暴露虚拟 DOM 之外的问题:
- 若 Scripting 时间占比高(>50%),说明 JS 执行太重 → 检查 computed、watch、mounted 中是否有同步循环或复杂计算
- 若 Rendering 或 Painting 占比突增,说明样式或布局频繁触发 → 查看是否用了
width: fit-content、inline-block等易引发重排的 CSS - 注意 Layout Shift 指标,它常和虚拟 DOM 更新后节点尺寸不稳定有关(比如图片缺宽高、字体加载延迟)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











