🔍Vue 3 + Pinia 切換頁面回來卡頓?完整分析與解決方案
前言
在單頁應用(SPA)開發中,Vue 3 + Pinia
是非常常見的組合,可以有效管理全域與頁面狀態。
但是許多開發者在實作「切換頁面再回來時保留資料」時,常常遇到一個問題:頁面回來後卡卡的、甚至又重新撈一次資料。
這篇文章將用一個實際案例,分析為什麼會卡頓、程式哪裡出了問題,以及如何修改程式碼讓切頁回來時瞬間顯示資料而不卡頓。
案例背景
假設我們有多個頁面(PageOne.vue、PageTwo.vue、PageThree.vue…),共同透過 Pinia 儲存:
-
全域選取的版本
globalApsVersion -
每個頁面的表頭、表格資料、篩選條件
在 PageOne.vue 中,我們在
onMounted() 嘗試恢復儲存的資料:
const saved = store.pageStates[pageKey] || {}
if (saved.selectedVersion && saved.mappedTableData?.length) {
selectedVersion.value = saved.selectedVersion
tableHeaders.value = saved.tableHeaders
mappedTableData.value = saved.mappedTableData
filters.value = saved.filters
initUniqueAndFilters()
await nextTick()
updateDummyScrollWidth()
applySticky()
} else {
await fetchPlanData()
}
看似沒問題,但實際上,這行:
selectedVersion.value = saved.selectedVersion
會觸發:
watch(selectedVersion, fetchPlanData)
導致一進頁面時又重新呼叫 API 撈資料,造成卡頓與延遲。
問題原因
-
selectedVersion 被改變 → 觸發 watch → 再次呼叫 API
雖然我們只是想恢復資料,但實際上卻觸發了版本監聽器,重複查詢資料。 -
watch 沒有防呆機制
預設的watch(selectedVersion, fetchPlanData)在首次載入時就會觸發,不管你是不是只是從 Pinia 恢復資料。 -
UI 沒有在 onActivated 重新套用 sticky 或 scroll 設定
如果使用<keep-alive>,切頁後回來 sticky 表頭可能失效,需要重新計算。
解決方案
1. 避免首次載入時觸發 API
不要在 onMounted() 中直接改
selectedVersion.value,改成:
if (saved?.selectedVersion && saved.mappedTableData?.length) {
// 直接還原資料
tableHeaders.value = saved.tableHeaders
mappedTableData.value = saved.mappedTableData
filters.value = saved.filters
initUniqueAndFilters()
await nextTick()
updateDummyScrollWidth()
applySticky()
} else if (selectedVersion.value) {
await fetchPlanData()
}
2. 在 watch 加防呆
let firstLoad = true
watch(selectedVersion, async (newVal, oldVal) => {
if (firstLoad) {
firstLoad = false
return
}
await fetchPlanData()
})
這樣首次載入時不會觸發 API,避免卡頓。
3. 在 onActivated 恢復 UI 狀態
onActivated(async () => {
const saved = store.pageStates[pageKey]
if (saved?.mappedTableData?.length) {
tableHeaders.value = saved.tableHeaders
mappedTableData.value = saved.mappedTableData
filters.value = saved.filters
initUniqueAndFilters()
await nextTick()
updateDummyScrollWidth()
applySticky()
}
})
確保切換回頁面時表格寬度、sticky 樣式都正確。
成果
修改後的效果:
-
切頁回來時 瞬間顯示上次資料,不卡頓
-
不會額外發送 API 請求
-
表頭 sticky 與捲動條正常顯示
結語
這個案例告訴我們:
-
狀態管理的恢復要小心觸發監聽器
-
watch 需要防呆機制
-
UI 狀態恢復要配合 onActivated 處理
這些細節不只是效能優化,更能提升使用者體驗。
如果你在 Vue 3 + Pinia
專案中遇到類似的問題,可以參考這套解法,保證切頁回來不卡頓。 🚀
留言
張貼留言