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 跑一下性能分析,找到瓶颈再动手,别瞎优化。