摘要:Vue3 凭借其响应式系统和组合式 API 带来了更好的开发体验,但若忽视性能优化,大型应用仍可能遭遇卡顿。本文将手把手教你 15+ 个 Vue3 性能优化技巧,涵盖 响应式陷阱、渲染优化、内存管理 等核心场景,助你打造丝滑应用!
一、响应式系统:精准控制,避免过度追踪 🔍
1. 不用响应式:响应式虽好,可不要贪杯
// 第三方插件不需要响应式
vxeTable.loadData(data) // data 不需要响应式
echart.setOption(option); // option 不需要响应式
<el-select v-model="value" > <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select>
// options 不更改,无需响应式
const option = [{
label: 'x',
value: 1
}]
// 当前组件能获取触发事件的,不用watch
<el-select v-model="value" @change="changeStyle" > ..... <el-select/>
// 错误
watch(value, () => {})
// 正确
const changeStyle = () => {}
// 不要先computed后watch
// 错误
const val1 = computed(()=>return props.xxx)
watch(val1,()=>{})
// 正确
watch(props.xxx,()=>{})
// ❌ 错误!在 computed 中修改状态
const badComputed = computed(() => {
count.value++; // 副作用操作
return count.value * 2;
});
// 深层响应式对象可能触发不必要的计算。
const shallowData = shallowReactive({
nested: { value: 1 } // 仅顶层响应
});
const badComputed = computed(() => {
return shallowData.value;
});
2. 浅层响应:告别无意义的深度监听
-
问题:
reactive
会递归追踪所有嵌套属性,大对象性能堪忧! -
方案:
✅shallowReactive
:仅追踪顶层属性
✅shallowRef
:跳过值的深层响应const shallowData = shallowReactive({ nested: { value: 1 } // 仅顶层响应 }); const shallowValue = shallowRef({ a: 1 }); // .value 变化才触发
<el-table :data="tableData"> ... </el-table> // 不关注具体元素,直接使用shallowRef const tableData = shallowRef([]); const getdata = ()=> { ... tableData.value = [...] }
<mychart :options="myoption"> </mychart> // 不关注具体元素,直接使用shallowRef const myoption = shallowRef({}); const getdata = ()=> { ... myoption.value = {...} }
3. 精准追踪:用 markRaw
标记非响应式对象
const rawConfig = markRaw({ apiUrl: '...' }); // 跳过响应式处理
const state = reactive({
config: rawConfig, // 不会被代理
data: []
});
<template>
<el-tabs v-model="activeName">
<el-tab-pane
v-for="pane in panes"
:key="pane.name"
:label="pane.label"
:name="pane.name">
</el-tab-pane>
</el-tabs>
<component :is="pane.activeComponent"></component>
</template>
<script setup>
import ComponentA from '.....'
const pane = reactive({
activeName: '',
activeComponent: null,
})
const panes = [
{
name: 1
label: 1
component: markRaw(ComponentA)
}
]
pane.activeComponent = panes[0].component
<script/>
二、组件渲染:减少重绘,极致高效 🎨
1. 列表渲染:长列表救星虚拟滚动
<template>
<!-- 使用 vue-virtual-scroller -->
<RecycleScroller
:items="bigList"
:item-size="50"
key-field="id"
>
<template v-slot="{ item }">
<div>{{ item.name }}</div>
</template>
</RecycleScroller>
</template>
2. v-memo
:记忆化静态节点(Vue3.2+)
<div
v-for="item in list"
:key="item.id"
v-memo="[item.id === selectedId]"
>
<!-- 仅当 item.id === selectedId 变化时重新渲染 -->
{{ item.name }}
</div>
3. 组件懒加载:按需渲染,首屏提速
// 路由懒加载
const UserProfile = defineAsyncComponent(() =>
import('./UserProfile.vue')
);
三、资源管理:严防内存泄漏,应用长青 🌲
1. 副作用清理:onUnmounted
必用!
// 组件卸载时清理定时器、事件监听等
setup() {
let timer;
const startTimer = () => {
timer = setInterval(() => console.log('Tick!'), 1000);
};
onUnmounted(() => {
clearInterval(timer);
window.removeEventListener('resize', handleResize);
});
}
2. 全局事件:用完即焚
// 错误!全局事件不清理会导致多次绑定
mounted() {
window.addEventListener('resize', this.handleResize);
}
// 正确✅
setup() {
const handleResize = () => { /* ... */ };
onMounted(() => {
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
}
四、高级技巧:压榨性能极限 💪
1. effectScope
:批量管理响应式作用域(Vue3.2+)
const scope = effectScope();
scope.run(() => {
watch(data1, () => { /* ... */ });
watch(data2, () => { /* ... */ });
});
// 组件卸载时一键清理所有 effect
onUnmounted(() => scope.stop());
2. 服务端渲染(SSR):首屏秒开
// 使用 @vue/server-renderer
import { renderToString } from '@vue/server-renderer';
const app = createSSRApp(App);
const html = await renderToString(app);
3. Web Workers:CPU 密集型任务后移
// 主线程
const worker = new Worker('./data-processor.js');
worker.postMessage(largeData);
worker.onmessage = (e) => {
result.value = e.data;
};
五、工具链:性能分析与监控 🔧
1. Vue DevTools 性能分析
- 查看组件渲染耗时
- 追踪响应式依赖
2. Chrome Performance 面板
- 录制运行时性能
- 分析脚本执行、渲染、内存占用
3. 内存泄漏检测
- Memory 快照 对比
- 查找分离的 DOM 节点
📋 性能优化检查清单
分类 | 检查项 | 是否完成 |
---|---|---|
不用响应式 | 响应式是必须的吗? | ✅/❌ |
响应式 | 是否使用 shallowReactive 优化深层对象? | ✅/❌ |
组件 | 长列表是否实现虚拟滚动? | ✅/❌ |
资源管理 | 所有副作用是否在 onUnmounted 清理? | ✅/❌ |
构建 | 是否启用代码分割和 Tree Shaking? | ✅/❌ |
结语:性能优化不是一蹴而就,而需结合具体场景持续调优。掌握这些 Vue3 优化技巧,让你的应用在用户体验和运行效率上双赢! 🏆
延伸阅读:
- Vue3 官方性能指南
- 《深入浅出 Vue.js 设计与实现》