Vue 性能优化
性能优化的核心不是盲目使用 API,而是先确认瓶颈,再减少不必要的加载、响应式追踪、组件更新和 DOM 操作。
一、先定位瓶颈
不要看到页面卡顿就直接加 v-memo 或虚拟列表。先区分问题发生在哪个阶段:
常用手段包括:浏览器 Performance 面板、Vue Devtools 的组件更新检查、构建产物分析,以及记录优化前后的首屏时间、交互延迟和内存占用。优化后必须用同一场景复测,避免把主观感受当成结论。
二、减少首屏加载成本
路由和组件懒加载
通过动态 import() 将不属于首屏的页面拆成独立 chunk,访问时再加载:
对于首屏不会出现的重量级组件,可以使用 defineAsyncComponent。应同时考虑 loading、error、超时和重试状态,避免网络失败时页面一直空白。异步组件的详细用法见异步组件。
控制产物体积
- 优先使用支持 Tree Shaking 的 ES Module 导入方式;
- 避免在首屏引入编辑器、图表库等重量级依赖;
- 对确实需要的大依赖做按页面或功能拆分;
- 用构建产物分析确认体积主要来自哪里,而不是只看源码大小。
懒加载会增加请求和加载状态管理成本。首屏必需内容不应为了拆包而过度延迟。
三、减少不必要的组件更新
设计稳定的组件边界
让组件只接收它真正需要的数据,避免把会频繁变化的整个大对象传给大量子组件。可以把高频变化区域拆成更小的组件,使更新范围更明确。
相比传入整个 user 对象,稳定、精确的 props 更容易让子组件跳过无关更新。需要注意:不要为了追求“稳定”而复制大量对象或增加复杂的计算,最终仍应以测量结果为准。
合理使用计算属性
对于依赖响应式数据的派生结果,使用 computed 可以缓存结果,并且只在依赖变化时重新计算;简单的一次性表达式不必强行抽成 computed。
computed 也不是万能缓存:如果每次都创建新的大对象,或依赖本身频繁变化,缓存收益会很有限。
避免不必要的深层响应式
大数据、第三方实例或本身不需要逐字段响应式的数据,不必全部交给深层代理:
shallowRef只追踪.value的替换,适合整体替换的数据或实例;markRaw适合第三方库实例、不可代理对象和不需要响应式的数据;- 使用浅层 API 后,深层修改不会自动触发更新,必须明确替换引用或手动触发。
四、列表和渲染优化
正确使用 key
v-for 应使用稳定且唯一的业务 ID:
不要默认使用数组下标。列表发生插入、删除或排序时,index 可能导致组件状态和 DOM 节点错误复用。只有列表永远不增删、不排序且没有内部状态时,才可以考虑使用下标。
虚拟列表
当列表包含成千上万条数据时,即使 Diff 很快,创建和维护大量真实 DOM 仍然昂贵。虚拟列表只渲染可视区域附近的项目,适合高度固定或可以估算高度的长列表。
使用虚拟列表前应处理好:
- 行高变化和动态高度测量;
- 键盘导航、滚动定位和加载更多;
- 快速滚动时的占位高度与白屏问题。
v-memo 与 v-once
v-memo 适合依赖明确、更新频率低的大型子树;依赖没有变化时可以跳过子树更新:
v-once 适合真正只需要渲染一次的内容。两者都应在确认存在更新瓶颈后使用,否则会增加理解和维护成本。Patch Flag、静态提升和 Block Tree 等编译时优化见Diff 算法。
v-if 和 v-show
v-if:条件为假时不创建 DOM,适合不常显示或创建成本较高的内容;v-show:始终创建 DOM,只切换display,适合频繁切换且内容较轻的区域。
选择时要同时考虑初始渲染成本、切换频率和隐藏内容是否占用资源,不能简单归纳为“频繁切换永远使用 v-show”。
五、事件、网络和缓存
高频滚动、拖拽和输入事件应避免在每次触发时执行昂贵逻辑,必要时使用节流、合并更新或把计算移出事件回调。事件监听、定时器和订阅必须在组件卸载时清理:
请求也要关注竞态:组件已经卸载或查询条件已经变化时,旧请求的结果不应覆盖新结果。可以使用 AbortController 或请求序列号取消、忽略过期响应。
KeepAlive 能缓存组件实例,减少反复创建的成本,但也会保留状态和资源。应配合 include、exclude 或 max 控制范围,并在 deactivated 时暂停不必要的轮询和监听。详见Keep-Alive。
六、常见误区
- 不是所有计算都需要
computed,不是所有列表都需要虚拟化; shallowRef和markRaw会改变响应式语义,不能只为“更快”而全局使用;nextTick只保证 DOM 更新批次已经刷新,不会让昂贵计算自动变快;v-memo、v-once可能让界面显示旧数据,使用前要确认依赖完整;- 防抖、节流、懒加载和缓存都会引入延迟、状态或一致性成本。
总结
Vue 性能优化可以按下面的顺序思考:
一句话总结:先让不需要加载的内容不加载,让不需要更新的组件不更新,让不需要存在的 DOM 不存在,最后用数据验证优化是否有效。

