Vue3性能優(yōu)化的5個隱藏技巧總結(jié)大全(第4個連老手都未必知道)
上周,我們上線了一個數(shù)據(jù)看板頁面,本地跑得飛快,一上生產(chǎn)——滾動卡成 PPT。
Profiler 一抓,發(fā)現(xiàn):
- 每次滾動都在重復(fù)創(chuàng)建
computed函數(shù) - 列表項里嵌套了 3 層
<Suspense> - 一個
watch竟然監(jiān)聽了整個reactive對象……
問題不在邏輯,而在 “你以為沒問題的寫法”。
今天,我就分享 5 個 Vue 3 中少有人提、但效果驚人的性能優(yōu)化技巧,尤其第 4 個,連很多 5 年經(jīng)驗的老手都沒用過。
技巧 1:別在模板里寫“方法調(diào)用”,用computed+ 緩存
反面教材:
<template>
<div>{{ formatUserName(user) }}</div> <!-- 每次渲染都執(zhí)行! -->
</template>
<script setup>
const formatUserName = (user) => `${user.firstName} ${user.lastName}`;
</script>
正確做法:
const formattedName = computed(() =>
`${user.value.firstName} ${user.value.lastName}`
);
<template>
<div>{{ formattedName }}</div> <!-- 響應(yīng)式緩存,依賴不變不重算 -->
</template>關(guān)鍵點:模板中的函數(shù)調(diào)用 沒有緩存,每次 re-render 都會執(zhí)行!
技巧 2:v-for里的組件,記得加key—— 但別用index!
很多人知道要加 key,但隨手寫:
<div v-for="(item, index) in list" :key="index"> <ItemCard :data="item" /> </div>
問題:當列表發(fā)生插入/刪除時,index 會變,導(dǎo)致 Vue 錯誤復(fù)用組件實例,引發(fā)狀態(tài)錯亂 or 不必要的銷毀重建。
正確做法:用唯一 ID
<div v-for="item in list" :key="item.id"> <ItemCard :data="item" /> </div>
如果真沒 ID?考慮用
Symbol()或crypto.randomUUID()生成穩(wěn)定 key(僅限靜態(tài)列表)。
技巧 3:慎用watch監(jiān)聽整個reactive對象
const state = reactive({ a: 1, b: 2, c: 3 });
watch(state, () => {
console.log('state changed');
});
這會導(dǎo)致:只要 a、b、c 任意一個變了,回調(diào)就觸發(fā),即使你只關(guān)心 a。
更精準的寫法:
// 方案 A:監(jiān)聽具體屬性
watch(() => state.a, (newVal) => { ... });
// 方案 B:用 toRefs 解構(gòu)后監(jiān)聽
const { a } = toRefs(state);
watch(a, (newVal) => { ... });
高級技巧:如果必須監(jiān)聽多個字段,用 getter 函數(shù)組合:
watch(
() => ({ a: state.a, b: state.b }),
(newVals) => { /* 只有 a 或 b 變才觸發(fā) */ }
);
技巧 4:用shallowRef和markRaw跳過不必要的響應(yīng)式(隱藏大招?。?/h2>
這是 Vue 3 響應(yīng)式系統(tǒng)中最被低估的 API。
場景:你有一個大型配置對象 or 第三方庫實例(如 echarts 實例),不需要響應(yīng)式?
默認寫法(性能殺手):
const chart = ref(null); // Vue 會嘗試把 echarts 實例變成響應(yīng)式!
onMounted(() => {
chart.value = echarts.init(dom); // 內(nèi)部 thousands of properties!
});
正確做法:
// 方案 A:用 shallowRef(只讓 .value 響應(yīng),內(nèi)部不遞歸) const chart = shallowRef(null); // 方案 B:用 markRaw 明確告訴 Vue “別動它” const chartInstance = markRaw(echarts.init(dom)); const chart = ref(chartInstance);
效果:避免 Vue 遞歸遍歷大型對象,節(jié)省內(nèi)存 + 提升初始化速度 10x+
適用場景:
- 圖表實例(ECharts、Chart.js)
- 復(fù)雜配置對象(如 Monaco Editor options)
- 不變的數(shù)據(jù)結(jié)構(gòu)(如路由 meta、常量字典)
技巧 5:懶加載組件 + 異步 setup,減少首屏負擔(dān)
別讓所有組件都在首屏加載!
<!-- 同步引入,打包進主 chunk --> <script setup> import HeavyChart from './HeavyChart.vue'; </script>
改成動態(tài)導(dǎo)入 + Suspense:
<template>
<Suspense>
<template #default>
<LazyChart />
</template>
<template #fallback>
<div>Loading chart...</div>
</template>
</Suspense>
</template>
<script setup>
// 自動代碼分割
const LazyChart = defineAsyncComponent(() => import('./HeavyChart.vue'));
</script>
進階:配合
IntersectionObserver實現(xiàn)滾動到可視區(qū)再加載:
const isVisible = ref(false); // 當元素進入視口,isVisible = true → 再加載組件
總結(jié):5 個技巧速查表
| 技巧 | 適用場景 | 性能收益 |
|---|---|---|
模板中用 computed 代替方法調(diào)用 | 頻繁渲染的格式化邏輯 | 避免重復(fù)計算 |
v-for 用唯一 ID 做 key | 動態(tài)列表(增刪改) | 減少 DOM 重建 |
精準 watch 而非監(jiān)聽整個對象 | 復(fù)雜狀態(tài)管理 | 避免無效回調(diào) |
shallowRef / markRaw 跳過響應(yīng)式 | 大型對象、第三方實例 | 內(nèi)存 & 初始化提速 |
| 異步組件 + Suspense | 重型組件(圖表、編輯器) | 首屏加載更快 |
最后說兩句
Vue 3 的性能,80% 取決于你如何使用響應(yīng)式系統(tǒng),而不是框架本身慢。
真正的優(yōu)化,不是“加緩存”“開 SSR”,而是:
在正確的地方,用正確的 API,做最小化的響應(yīng)式。
下次寫組件前,先問自己:
“這個數(shù)據(jù),真的需要響應(yīng)式嗎?”
到此這篇關(guān)于Vue3性能優(yōu)化的5個隱藏技巧總結(jié)大全的文章就介紹到這了,更多相關(guān)Vue3性能優(yōu)化隱藏技巧內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用el-table做成樹形結(jié)構(gòu)并解決數(shù)據(jù)驅(qū)動視圖問題
這篇文章主要介紹了使用el-table做成樹形結(jié)構(gòu)并解決數(shù)據(jù)驅(qū)動視圖問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
van-uploader保存文件到后端回顯后端接口返回的數(shù)據(jù)
前端開發(fā)想省時間就是要找框架呀,下面這篇文章主要給大家介紹了關(guān)于van-uploader保存文件到后端回顯后端接口返回的數(shù)據(jù),文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-06-06
Vue2.0仿餓了么webapp單頁面應(yīng)用詳細步驟
本篇文章給大家分享了Vue2.0仿餓了么webapp單頁面應(yīng)用詳細步驟,有興趣的朋友可以跟著操作下。2018-07-07
利用Vue v-model實現(xiàn)一個自定義的表單組件
本篇文章主要介紹了利用Vue v-model實現(xiàn)一個自定義的表單組件的相關(guān)知識。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04

