Organize fetch state in vue
在前端請求資料是一場災難,但事情不必這麼複雜! feat. Vue
背景
索取並顯示資料對前端工程師來說是家常便飯的事,但隨著背後延伸的狀態越來越多,就會讓整個專案極度混亂,因此想要藉由這篇文章點出現有問題並提出一些可行的方案,紀錄尋找更高效解法的過程。
雖然文章中使用的是 Vue Composition API 不過重點不在於使用的框架而是背後的概念。像是 React 的脈絡也是類似的,如果你想從 React 的角度切入推薦這篇文章:为什么你不应该在 React 中直接使用 useEffect 从 API 获取数据🔗
Lv.1:從發送一個簡單的請求開始
目前有一個簡單的產品 API🔗,需求是把資料索取下來並且顯示在畫面上,這裡使用 JS 原生的 fetch API🔗 + Async / Await🔗 來處理非同步請求,並且透過狀態來驅動畫面。
1️⃣ 檢討
需求達成了,但你發現這麼做並沒有辦法顯示請求出錯或是加載的狀態,用戶無法知道任何進展!因此下一版本來嘗試新增更多狀態來處理這個問題。
Lv.2:新增加載與錯誤狀態
在這個版本使用更多狀態像是 isLoading
或 errorMessage
來記錄請求的狀態,並且透過這些狀態來驅動 UI 給用戶更多提示。
2️⃣ 檢討
到這裡用戶使用體驗已經接近完善了,但開發體驗卻不盡人意,因為當規模擴大或需求變更時,元件終將會塞滿各式各樣的狀態,光是理解這些狀態避免切換錯誤就是一件很累人且容易出錯的事。除此之外加載過程的版面偏移🔗造成的閃爍除了影響用戶體驗之外,重新計算頁面布局也會造成性能上的問題,下一版本來嘗試製作 UI 並解決這個問題。
Lv.3:添加 UI 與加載骨架
這次版本除了給資料撰寫基本樣式之外也新增了骨架 UI,其實就是更貼近實際結果更華麗的 Loader 而已,這麼做的好處是可以解決先前遇到的版面偏移。
3️⃣ 檢討
到這個步驟,用戶體驗已非常完美,但在狀態管理方面則可以考慮以下幾種方案來增進開發體驗。
Lv.3-1:透過組合式函數(Composable)包裝邏輯
反思處理這些狀態的過程,發現其實這些狀態都是為了處理資料的請求,因此可以透過包裝相關邏輯來處理這些狀態,讓元件只需要關注資料本身即可。舉例來說製作一個 useFetch
並且輸入請求 URL 並且輸出資料、錯誤訊息、請求狀態……等,不用再替每個請求開開關關狀態。
細節實作可以參考官方案例🔗、 VueUse 的實作🔗或是 Nuxt 實作🔗,在這之上可以擴充更多功能像是快取、重試、渲染模式切換……等進階功能。
Lv.3-2:使用實驗性 <Suspense>
元件
<Suspense>
實際上就是一個「Vue 的預設元件用於處理異步載入的元件」,可以在異步元件加載完成之前顯示預設內容,<Suspense>
會接受兩個插槽🔗分別是 default
與 fallback
,它們用途也很明顯:default
用於放入異步元件,fallback
則是放入預設元件(加載告示之類的訊息)。
所謂的異步元件其實就是兩種可能:1. async setup()
或是 top level await
🔗。
所以這樣我們可以直白的製作一個異步元件 AsyncProductCard
(如下),並且透過上一層的 <Suspense>
幫助我們在元件加載完成之前自動顯示預設內容。
至於錯誤處理可以使用 Vue3 的 onErrorCaptured🔗 生命週期,這個生命週期可以捕捉子元件的錯誤,並且可以在上層元件中處理錯誤,如此一來請求錯誤也可以顯示反饋給用戶了。
總結
文章循序漸進的展示如何在 Vue 中實踐改良索取資料的用戶與開發體驗,有將過程記錄在 Vue-Fetch-Demo🔗 這個檔案之中,歡迎自由索取練習。
延伸閱讀