EP44 - 懸掛

更新 發佈閱讀 12 分鐘
Suspense,這也是新觀念~
但應該跟異步有點關係吧?
快來看看吧!
每天看一篇文章~希望能持續下去啊!
大家會想什麼內容呢?快來留言吧

實驗性功能

<Suspense> 是一個實驗性功能。它不保證會達到穩定狀態,並且 API 在達到穩定狀態之前可能會發生變化。

<Suspense> 是一個內建組件,用於在組件樹中協調異步依賴。它可以在等待組件樹中的多個嵌套異步依賴解決時,渲染一個加載狀態。

異步依賴 - Async Dependencies​

為了解釋 <Suspense> 嘗試解決的問題以及它如何與這些異步依賴進行互動,讓我們想像一個如下的組件層次結構:

<Suspense>
└─ <Dashboard>
├─ <Profile>
│ └─ <FriendStatus> (具有異步 setup() 的組件)
└─ <Content>
├─ <ActivityFeed> (異步組件)
└─ <Stats> (異步組件)

在這個組件樹中,有多個嵌套組件的渲染依賴於首先解決一些異步資源。沒有 <Suspense> 的情況下,每個組件都需要處理自己的加載/錯誤和已加載狀態。在最糟糕的情況下,我們可能會在頁面上看到三個加載旋轉器,並且內容會在不同的時間顯示出來。

<Suspense> 組件使我們能夠在等待這些嵌套異步依賴解決時,顯示頂層的加載/錯誤狀態。

<Suspense> 可以等待兩種類型的異步依賴:

  1. 具有異步 setup() 鉤子的組件。這包括使用 <script setup> 並帶有頂層 await 表達式的組件。
  2. 異步組件

異步 setup() - async setup()

Composition API 組件的 setup() 鉤子可以是異步的:

export default {
async setup() {
const res = await fetch(...)
const posts = await res.json()
return {
posts
}
}
}

如果使用 <script setup>,頂層 await 表達式的存在會自動使組件成為異步依賴:

<script setup>
const res = await fetch(...)
const posts = await res.json()
</script>

<template>
{{ posts }}
</template>

異步組件 - Async Components

異步組件默認是“可暫停”的。這意味著如果它在父鏈中有 <Suspense>,它將被視為該 <Suspense> 的異步依賴。在這種情況下,加載狀態將由 <Suspense> 控制,而組件本身的加載、錯誤、延遲和超時選項將被忽略。

異步組件可以通過在其選項中指定 suspensible: false 來選擇不受 <Suspense> 控制,並讓組件始終控制其自己的加載狀態。

加載狀態 - Loading State

<Suspense> 組件有兩個插槽:#default#fallback。這兩個插槽都只允許一個直接的子節點。如果可能,將顯示默認插槽中的節點。如果不可能,將顯示回退插槽中的節點。

<template>
<Suspense>
<!-- 具有嵌套異步依賴的組件 -->
<Dashboard />

<!-- 通過 #fallback 插槽顯示加載狀態 -->
<template #fallback>
Loading...
</template>
</Suspense>
</template>

在初始渲染時,<Suspense> 會在內存中渲染其默認插槽內容。如果在此過程中遇到任何異步依賴,它將進入等待狀態。在等待狀態期間,將顯示回退內容。當所有遇到的異步依賴解決後,<Suspense> 進入已解決狀態,並顯示已解決的默認插槽內容。

如果在初始渲染期間沒有遇到異步依賴,<Suspense> 將直接進入已解決狀態。

一旦進入已解決狀態,只有在 #default 插槽的根節點被替換時,<Suspense> 才會恢復到等待狀態。嵌套在樹中更深處的新異步依賴不會導致 <Suspense> 恢復到等待狀態。

當發生恢復時,不會立即顯示回退內容。相反,<Suspense> 將顯示之前的 #default 內容,同時等待新內容及其異步依賴被解決。這種行為可以通過 timeout 屬性配置:如果渲染新默認內容花費的時間超過 timeout<Suspense> 將切換到回退內容。timeout 值為 0 時,當默認內容被替換時,將立即顯示回退內容。

事件 - Events

<Suspense> 組件會觸發三個事件:pendingresolvefallbackpending 事件在進入等待狀態時觸發。resolve 事件在默認插槽的新內容解析完成時觸發。fallback 事件在顯示回退插槽內容時觸發。

這些事件可以用來在新組件加載時,在舊的 DOM 前顯示加載指示器。

錯誤處理 - Error Handling​

<Suspense> 目前不通過自身組件提供錯誤處理功能——然而,你可以使用 errorCaptured 選項或 onErrorCaptured() 鉤子在 <Suspense> 的父組件中捕獲並處理異步錯誤。

結合其他組件 - Combining with Other Components​

通常會希望將 <Suspense><Transition><KeepAlive> 組件結合使用。這些組件的嵌套順序對於正確運行它們非常重要。

此外,這些組件經常與 Vue Router 的 <RouterView> 組件一起使用。

下面的範例展示了如何嵌套這些組件,以便它們都能按預期運行。對於較簡單的組合,可以移除不需要的組件:

<template>
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Transition mode="out-in">
<KeepAlive>
<Suspense>
<!-- 主內容 -->
<component :is="Component"></component>

<!-- 加載狀態 -->
<template #fallback>
Loading...
</template>
</Suspense>
</KeepAlive>
</Transition>
</template>
</RouterView>
</template>

Vue Router 支援使用動態導入來延遲加載組件。這些與異步組件不同,且目前不會觸發 <Suspense>。然而,它們仍然可以有異步組件作為後代,並且這些後代可以按照通常方式觸發 <Suspense>

嵌套的 Suspense - Nested Suspense​

僅支援於 3.3+

當我們有多個異步組件(常見於嵌套或基於佈局的路由)時,如下所示:

<template>
<Suspense>
<component :is="DynamicAsyncOuter">
<component :is="DynamicAsyncInner" />
</component>
</Suspense>
</template>

<Suspense> 會如預期地創建一個邊界,解決樹狀結構中的所有異步組件。然而,當我們更改 DynamicAsyncOuter 時,<Suspense> 會正確等待,但當我們更改 DynamicAsyncInner 時,嵌套的 DynamicAsyncInner 會在解析完成之前渲染一個空節點(而不是先前的節點或 fallback 插槽)。

為了解決這個問題,我們可以使用嵌套的 suspense 來處理嵌套組件的補丁,如下所示:

<template>
<Suspense>
<component :is="DynamicAsyncOuter">
<Suspense suspensible> <!-- 這裡 -->
<component :is="DynamicAsyncInner" />
</Suspense>
</component>
</Suspense>
</template>

如果不設置 suspensible 屬性,內部的 <Suspense> 會被父級 <Suspense> 視為同步組件。這意味著它有自己的 fallback 插槽,如果兩個動態組件同時變更,可能會出現空節點和多個補丁週期,而子級 <Suspense> 正在加載其自己的依賴樹,這可能是不理想的。設置 suspensible 屬性後,所有的異步依賴處理將交給父級 <Suspense>(包括觸發的事件),而內部的 <Suspense> 僅作為另一個依賴解析和補丁的邊界。

相關文件

看完這些文章還是沒有很懂www
應該就是應用在以下情境中

是的,<Suspense> 的主要應用之一是處理加載狀態,但它的用途不僅限於加載器。以下是一些 <Suspense> 可以用於的場景:

  1. 異步數據獲取:
    • 當一個組件需要從 API 獲取數據時,可以使用 <Suspense> 來管理加載狀態,避免顯示未加載的數據。
  2. 異步路由加載:
    • 在使用 Vue Router 時,<Suspense> 可以用於處理異步路由組件的加載,這樣在導航到新路由時可以顯示加載指示器。
  3. 組件樹的異步加載:
    • 當有多個嵌套的組件需要異步加載時,<Suspense> 可以協調它們的加載,確保在所有依賴被解析之前不會顯示任何內容。
  4. 錯誤處理:
    • 雖然 <Suspense> 本身不提供錯誤處理,但可以與其他錯誤捕獲組件(如 errorCaptured)結合使用,以便在異步加載過程中捕獲並處理錯誤。
  5. 視覺效果和過渡:
    • <Transition> 組件結合使用時,可以在加載或變更組件時應用過渡效果,增強用戶體驗。
  6. 整合和組織代碼:
    • 將異步邏輯封裝在 <Suspense> 中可以幫助組織代碼,保持組件的簡潔性,讓異步邏輯更具可讀性和可維護性。

總結

<Suspense> 提供了一種優雅的方式來處理異步組件的加載和錯誤管理,無論是用於單個組件的加載,還是多個組件的嵌套加載,它都能幫助開發者改善用戶體驗。

留言
avatar-img
留言分享你的想法!
avatar-img
卡關的人生
2會員
73內容數
分享生活趣事~
卡關的人生的其他內容
2024/11/10
Vue 提供了多種動畫技術來提升應用程式的互動性,包括基於 CSS 類別的動畫、基於狀態的動畫,以及使用監視器來動畫化數值。基於類別的動畫可通過動態添加 CSS 類別來觸發,像是觸發按鈕搖動效果。基於狀態的動畫則是透過樣式綁定,根據互動動態調整元素的外觀,例如根據滑鼠位置改變背景顏色。
Thumbnail
2024/11/10
Vue 提供了多種動畫技術來提升應用程式的互動性,包括基於 CSS 類別的動畫、基於狀態的動畫,以及使用監視器來動畫化數值。基於類別的動畫可通過動態添加 CSS 類別來觸發,像是觸發按鈕搖動效果。基於狀態的動畫則是透過樣式綁定,根據互動動態調整元素的外觀,例如根據滑鼠位置改變背景顏色。
Thumbnail
2024/11/09
Web Components 是一組網頁原生 API,允許開發者創建可重複使用的自訂元素。Vue 與 Web Components 是互補的技術,Vue 支援整合和創建自訂元素。
Thumbnail
2024/11/09
Web Components 是一組網頁原生 API,允許開發者創建可重複使用的自訂元素。Vue 與 Web Components 是互補的技術,Vue 支援整合和創建自訂元素。
Thumbnail
2024/11/08
Vue 建議使用模板構建應用程式,但在需要 JavaScript 的全程式化功能時,渲染函數可派上用場。渲染函數通過 h() 函數創建 vnode,h 是 hyperscript 的簡寫,能生成 HTML 的 JavaScript。
Thumbnail
2024/11/08
Vue 建議使用模板構建應用程式,但在需要 JavaScript 的全程式化功能時,渲染函數可派上用場。渲染函數通過 h() 函數創建 vnode,h 是 hyperscript 的簡寫,能生成 HTML 的 JavaScript。
Thumbnail
看更多
你可能也想看
Thumbnail
在小小的租屋房間裡,透過蝦皮購物平臺採購各種黏土、模型、美甲材料等創作素材,打造專屬黏土小宇宙的療癒過程。文中分享多個蝦皮挖寶地圖,並推薦蝦皮分潤計畫。
Thumbnail
在小小的租屋房間裡,透過蝦皮購物平臺採購各種黏土、模型、美甲材料等創作素材,打造專屬黏土小宇宙的療癒過程。文中分享多個蝦皮挖寶地圖,並推薦蝦皮分潤計畫。
Thumbnail
小蝸和小豬因購物習慣不同常起衝突,直到發現蝦皮分潤計畫,讓小豬的購物愛好產生價值,也讓小蝸開始欣賞另一半的興趣。想增加收入或改善伴侶間的購物觀念差異?讓蝦皮分潤計畫成為你們的神隊友吧!
Thumbnail
小蝸和小豬因購物習慣不同常起衝突,直到發現蝦皮分潤計畫,讓小豬的購物愛好產生價值,也讓小蝸開始欣賞另一半的興趣。想增加收入或改善伴侶間的購物觀念差異?讓蝦皮分潤計畫成為你們的神隊友吧!
Thumbnail
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
Quasar Dialog 的 Invoking custom component 很好用,但是有些困擾的地方,一起來看看有甚麼辦法吧。
Thumbnail
Quasar Dialog 的 Invoking custom component 很好用,但是有些困擾的地方,一起來看看有甚麼辦法吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
因為最近想嘗試編碼風格,於是就選了一套比較"不嚴格"的輔助工具來摸索。 編輯器 VS CODE 框架 VUE3 打包工具 VITE 編碼風格 Standard 環境 version { "nodejs":"v18.18.0", "npm":"9.8.1" }
Thumbnail
因為最近想嘗試編碼風格,於是就選了一套比較"不嚴格"的輔助工具來摸索。 編輯器 VS CODE 框架 VUE3 打包工具 VITE 編碼風格 Standard 環境 version { "nodejs":"v18.18.0", "npm":"9.8.1" }
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
這是為了搭建自己想要的工作流而開始的研究工作。
Thumbnail
這是為了搭建自己想要的工作流而開始的研究工作。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News