🔍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
專案中遇到類似的問題,可以參考這套解法,保證切頁回來不卡頓。 🚀
留言
張貼留言