一、Vue2 性能优化笔记
1. 响应式与数据
只把需要响应的数据放进
data
常量、配置、纯展示数据可放在created外、普通变量或this.$options中,减少Object.defineProperty递归转换。大只读列表用
Object.freezejsthis.list = Object.freeze(bigList);冻结后 Vue2 不会做响应式转换,适合不需要修改的长列表。
新增/删除对象属性必须用
Vue.set/Vue.deletejsthis.$set(this.obj, "name", "vue"); this.$delete(this.obj, "name");数组索引赋值、修改 length 不会触发更新
用splice、push、pop等重写方法,或直接替换整个数组。慎用
watch deep: true
深度监听大对象开销高,尽量监听具体字段,或用computed派生。computed有缓存,methods没有
模板里避免复杂表达式和频繁调用的方法,能抽成computed就抽。避免
$forceUpdate
它会导致整个组件重新渲染,应优先修正响应式数据问题。
2. 模板与组件
v-for必须加唯一key
不要用index作为会增删排序列表的 key。避免
v-for和v-if同用
Vue2 中v-for优先级高于v-if,会先循环再判断,浪费性能。
正确做法:先过滤数据,再循环。v-if与v-show合理选择- 初始不渲染、切换少:
v-if - 频繁切换:
v-show
- 初始不渲染、切换少:
静态内容用
v-once/v-prev-once:只渲染一次,后续跳过更新。v-pre:跳过编译,适合纯静态大段内容。
keep-alive缓存组件vue<keep-alive :include="['List']"> <router-view /> </keep-alive>配合
activated/deactivated管理数据刷新,但注意内存占用。长列表用虚拟滚动
如vue-virtual-scroller,只渲染可视区域。纯展示组件可用函数式组件
jsexport default { functional: true, render(h, context) {}, };无状态、无实例,开销更小。
拆分组件,缩小更新范围
避免一个数据变化导致大组件整体重渲染。
3. 路由与构建
路由懒加载
jsconst Home = () => import("@/views/Home.vue");组件异步加载
jsconst AsyncComp = () => import("@/components/Heavy.vue");UI 库按需引入
Element UI、Ant Design Vue 等使用babel-plugin-component或按需导入。Webpack 优化
splitChunks分包externals+ CDN 引入 Vue、Vue Router、Vuexgzip/brotli压缩webpack-bundle-analyzer分析体积thread-loader多线程构建DLL、缓存、HappyPack 等按需使用
图片与静态资源
压缩、WebP、懒加载loading="lazy"、CDN、雪碧图、字体图标。
4. 运行时与清理
防抖节流
搜索、滚动、resize、输入等高频操作加防抖节流。组件销毁时清理
beforeDestroy/destroyed中清除:- 定时器
- 事件监听
- 全局事件总线
$off - 未完成请求
- 第三方实例
$nextTick批量更新
数据变化后需要操作 DOM 时使用,避免重复手动操作。复杂计算放 Web Worker
大数据解析、加密、计算等不阻塞主线程。
5. 首屏与网络
- 路由懒加载 + 按需引入 + CDN + gzip。
- HTTP 缓存、CDN、HTTP2。
- 接口分页、合并请求、取消重复请求。
- 骨架屏、Loading、错误捕获
errorCaptured。 - SSR / 预渲染:Nuxt2、
prerender-spa-plugin。
6. Vue2 优化优先级
路由懒加载 → 按需引入 → 图片优化 → gzip/CDN → v-for key → 虚拟列表 → keep-alive → Object.freeze → 清理副作用 → SSR/预渲染
二、Vue3 性能优化笔记
1. 响应式与数据
Vue3 使用 Proxy,新增/删除属性自动响应
不再需要Vue.set/Vue.delete。大对象用浅响应
jsimport { shallowRef, shallowReactive } from "vue"; const bigList = shallowRef([]); // 只追踪 .value 整体替换 const state = shallowReactive({}); // 只追踪顶层属性永不响应式的对象用
markRawjsimport { markRaw } from "vue"; const chart = markRaw(new Chart());临时读取原始对象用
toRawjsimport { toRaw } from "vue"; const raw = toRaw(proxyObj);操作原始对象不会触发更新,适合只读或临时计算。
只读大对象可用
readonly或Object.freeze
防止误改,也能减少不必要的追踪。ref/reactive选择- 基本类型:
ref - 对象:
reactive或ref - 大对象:
shallowRef/shallowReactive
- 基本类型:
computed缓存,watch精确监听
避免watch大对象且deep: true,尽量监听具体字段。effectScope统一停止副作用
适合组合式函数中批量管理watch、computed。
2. 模板与组件
v-for加唯一key
与 Vue2 一致。大列表用
v-memovue<div v-for="item in list" :key="item.id" v-memo="[item.id === selectedId]"> {{ item.name }} </div>条件跳过子树更新,适合长列表。
v-once/v-pre仍可用
静态内容优化。v-if与v-show合理选择
同 Vue2。defineAsyncComponent异步组件jsimport { defineAsyncComponent } from "vue"; const Heavy = defineAsyncComponent(() => import("./Heavy.vue"));Suspense处理异步依赖
配合异步组件,优化加载体验。Teleport优化弹窗层级
把 Modal、Toast 传送到body,避免深层嵌套和样式干扰。keep-alive缓存组件
生命周期改为onActivated/onDeactivated。长列表虚拟滚动
如vue-virtual-scroller、vueuc。拆分组件 +
script setupscript setup编译后更高效,减少this开销。
3. 编译与构建优化
Vue3 编译优化
- 静态提升
- Patch Flag
- 事件缓存
- Tree-shaking 更好
Vite / Rollup 优化
- 依赖预构建
manualChunks分包- gzip / brotli
- CDN 引入大依赖
按需引入
js// vite.config.js import Components from "unplugin-vue-components/vite"; import AutoImport from "unplugin-auto-import/vite";自动导入 Vue、Pinia、UI 库组件和 API。
状态管理用 Pinia
比 Vuex 更轻量,对 Tree-shaking 更友好。路由懒加载
jsconst Home = () => import("@/views/Home.vue");
4. 运行时与清理
onBeforeUnmount/onUnmounted清理副作用
清除定时器、事件监听、请求、第三方实例。防抖节流、
requestAnimationFrame
高频操作优化。Web Worker 处理复杂计算
避免阻塞主线程。nextTick批量更新 DOM
与 Vue2 类似。错误边界
onErrorCaptured
捕获子组件错误,避免白屏。
5. 首屏与网络
- 路由懒加载 + 按需引入 + CDN + gzip/brotli。
- HTTP 缓存、HTTP2、CDN。
- 接口分页、合并请求、取消重复请求。
- 骨架屏、Loading、错误边界。
- SSR / SSG:Nuxt3、Vue SSR。
- PWA / Service Worker 离线缓存。
- 性能监控:Lighthouse、Performance、Vue Devtools、Sentry。
6. Vue3 优化优先级
路由懒加载 → 按需引入 → 图片优化 → gzip/CDN → v-for key → v-memo → 虚拟列表 → shallowRef / markRaw → defineAsyncComponent → 清理副作用 → SSR/SSG
三、Vue2 / Vue3 优化差异速查表
| 优化点 | Vue2 | Vue3 |
|---|---|---|
| 响应式原理 | Object.defineProperty | Proxy |
| 新增/删除属性 | 必须 Vue.set / Vue.delete | 自动响应 |
| 大对象浅响应 | Object.freeze | shallowRef、shallowReactive |
| 标记非响应式 | 无直接 API,放 data 外 | markRaw、toRaw |
| 异步组件 | () => import() / 工厂函数 | defineAsyncComponent |
| 编译优化 | 较少 | 静态提升、Patch Flag、事件缓存 |
| 列表缓存 | v-once | v-once、v-memo |
| 异步依赖 | 手动 loading | Suspense |
| DOM 传送 | 手动或第三方 | Teleport |
| 构建工具 | Vue CLI + Webpack | Vite + Rollup / Webpack |
| 状态管理 | Vuex | Pinia |
| 生命周期清理 | beforeDestroy / destroyed | onBeforeUnmount / onUnmounted |
| keep-alive 生命周期 | activated / deactivated | onActivated / onDeactivated |
| Tree-shaking | 一般 | 更好 |
| SSR | Nuxt2 / Vue SSR | Nuxt3 / Vue SSR |
四、通用优化口诀
- 先量化再优化:Lighthouse、Performance、Vue Devtools。
- 首屏优先:路由懒加载、按需引入、CDN、gzip、图片优化。
- 渲染优先:
key、computed、v-if/v-show、虚拟列表、keep-alive。 - 响应式优先:Vue2 用
Object.freeze,Vue3 用shallowRef/markRaw。 - 运行时优先:防抖节流、清理副作用、Web Worker。
- Vue3 额外武器:
v-memo、defineAsyncComponent、Suspense、Teleport、Vite 分包。