Vue 3 相较于 Vue 2 在底层进行了诸多优化(例如使用了 Proxy 进行响应式系统重构、编译时优化等),但开发者仍需遵循最佳实践才能发挥其最大性能。
以下是 Vue 3 性能优化的核心技巧和最佳实践:
一、 编译时和渲染优化
1. 使用 v-if 代替 v-show (按需渲染)
- 优化点: 减少初始渲染和内存消耗。
- 做法: 当组件或元素在运行时很少切换或初始状态为隐藏时,使用
v-if。v-if具有更高的切换开销(销毁和重建),但它确保了只有在条件为真时才会创建组件实例和 DOM 元素。v-show只是切换 CSS 的display属性,无论条件如何,元素都会被渲染,切换开销低,但初始渲染开销大。
2. 利用 Vue 的编译优化(Template 编写规范)
Vue 3 编译器会自动进行静态提升(Static Hoisting)和块树(Block Tree)优化。
静态内容提升 (
hoistStatic):- 做法: 将不包含任何响应式数据的静态内容(如纯文本、静态 HTML 元素)放在组件模板中,Vue 3 会将其提升到组件外部,只创建一次,后续渲染时直接重用,减少虚拟 DOM 对比开销。
- 避免: 尽量避免对静态内容进行不必要的动态绑定。
使用
<template>避免不必要的层级:- 做法: 尽可能使用
<template>标签包裹多个根元素,而不是多余的<div>。<template>不会渲染成真实的 DOM 节点,可以减少 DOM 树深度。
- 做法: 尽可能使用
3. 列表渲染优化:使用 key
- 优化点: 提高列表更新时的 Diff 算法效率。
- 做法: 在所有使用
v-for进行列表渲染的元素上,务必提供稳定且唯一的:key属性(通常是数据的唯一 ID)。 - 避免: 不要使用数组索引
index作为key,除非列表项永远不会变动、新增或删除,否则会导致性能问题和状态错误。
二、 响应式系统优化
4. 避免不必要的深度侦听(Deep Watchers)
- 优化点: 减少侦听器遍历数据结构带来的巨大开销。
- 做法: 仅在必要时使用
watch的deep: true选项。如果只需要侦听对象内部某个具体的属性,直接写出该属性的路径,例如:() => user.name,而不是侦听整个user对象。
5. 避免在模板中使用复杂表达式
- 优化点: 减少不必要的计算和重复执行。
- 做法: * 避免在模板表达式中调用函数(如
{ { formatPrice(item.price) }}),因为每次组件重新渲染时,该函数都会被调用。- 对于依赖响应式数据的复杂计算,使用
computed属性。计算属性有缓存,只有在其依赖项发生变化时才会重新计算。
- 对于依赖响应式数据的复杂计算,使用
6. 使用 shallowRef 和 shallowReactive
- 优化点: 跳过深层响应式转换,提高大型或复杂数据的处理速度。
- 做法:
- 当你确定只需要让数据的顶层属性具备响应式时,使用
shallowReactive()。 - 当你需要一个非响应式的值,但又想通过替换整个值来触发更新时,使用
shallowRef()。
- 当你确定只需要让数据的顶层属性具备响应式时,使用
三、 组件优化和懒加载
7. 组件懒加载 (Lazy Loading)
- 优化点: 减少应用程序的初始加载时间。
- 做法: 对于非首屏或用户不常访问的组件,使用动态导入(Dynamic Import)和 Vue 的
defineAsyncComponent进行组件级别的懒加载。
// 路由懒加载 (常用)
const Home = () => import('./views/Home.vue');
// 组件懒加载
import {
defineAsyncComponent } from 'vue';
const MyModal = defineAsyncComponent(() =>
import('./components/MyModal.vue')
);
8. 路由懒加载
- 优化点: 将应用打包成更小的块(Chunks),按需加载,提升首屏速度。
- 做法: 在 Vue Router 中使用动态
import()语法来定义路由组件。
9. 适当使用函数式组件(Functional Components)
- 优化点: 减少组件实例的开销。
- 做法: 当组件是纯展示型、无状态、无生命周期钩子时,可以将其定义为函数式组件。这在渲染大量小型 UI 元素时特别有效。
四、 其他通用优化
10. 资源压缩和打包优化
- Tree Shaking: 确保你的构建工具(如 Vite/Webpack)配置了 Tree Shaking,以移除未使用的代码。
- 图片优化: 压缩图片、使用 WebP 等现代格式。
- CDN: 将静态资源(如 Vue 库本身、大型图片)托管到 CDN。
11. 虚拟列表 (Virtual Scroller)
- 优化点: 解决渲染大量列表数据(如超过 1000 条)时的性能问题。
- 做法: 对于超长列表,只渲染用户可见区域内的 DOM 元素,并在用户滚动时动态替换内容。这需要使用 第三方库 (如
vue-virtual-scroller) 或自定义实现。