Vue 性能优化指南
让你的页面飞起来
渲染优化
v-if vs v-show 怎么选?
- v-if:不渲染 DOM,适合"不常变"的内容
- v-show:渲染但不显示,适合"频繁切换"的内容
简单说:频繁切换用 v-show,偶尔显示用 v-if。
v-for 必须加 key
而且别用 index,用数据的唯一 ID。这样 Vue 的 Diff 算法才能正确复用节点。
computed 必须用
需要计算的值,用 computed 不要用 methods:
<!-- ❌ methods 每次渲染都重新算 -->
<span>{{ getFullName() }}</span>
<!-- ✅ computed 会缓存,结果不变就不重新算 -->
<span>{{ fullName }}</span>
v-memo 大杀器 (Vue 3.2+)
对于长列表,v-memo 是神器:
<div v-for="item in list" :key="item.id" v-memo="[item.done]">
...
</div>
只要 item.done 没变,整个子树 Diff 直接跳过。
虚拟列表
数据上千条?不要全部渲染。用 vue-virtual-scroller 这种库,只渲染可视区域的那十几条。
加载优化
路由懒加载
{
path: '/about',
component: () => import('./About.vue') // 异步加载
}
这样打包时会拆成单独的 JS 文件,首屏加载快很多。
异步组件
首屏不用的组件,用 defineAsyncComponent 延迟加载:
<script setup>
import { defineAsyncComponent } from "vue";
const HeavyChart = defineAsyncComponent(() => import("./HeavyChart.vue"));
</script>
<template>
<HeavyChart v-if="showChart" />
</template>
组件库按需引入
用 unplugin-vue-components 自动按需加载,不要全量引入:
// ❌ 全量引入
import { Button, Select, Input } from "element-plus";
// ✅ 按需引入(自动处理)
// 只需要在组件里用 <el-button>,自动按需加载
响应式优化
shallowRef
对于大对象(比如从接口拿来的大 JSON、ECharts 实例),用 shallowRef:
// ❌ deep ref,Vue 会递归监听所有属性,超级慢
const data = ref(veryBigObject);
// ✅ shallow ref,只监听 .value 变化,内部属性不监听
const data = shallowRef(veryBigObject);
避免内存泄漏
组件销毁时务必清理:
onUnmounted(() => {
clearInterval(timer);
window.removeEventListener("resize", handler);
socket.disconnect();
});
Vue 3 内置优化(不用你管)
Vue 3 编译器自动帮你做了:
- 静态提升:静态节点不参与 Diff
- Patch Flags:编译时标记哪些是动态的,Diff 时直接跳过
这些是 Vue 3 相比 Vue 2 性能提升的关键。
总结
| 优化点 | 做法 |
|---|
| 渲染 | v-if/v-show 选对、v-for 加 key、computed |
| 加载 | 路由懒加载、异步组件、按需引入 |
| 响应式 | shallowRef 大对象、及时清理定时器/事件 |
| Vue 3 | 用就对了,自动优化 |
记住:优化之前先用 DevTools 跑一下性能分析,找到瓶颈再动手,别瞎优化。