Vue3中的新特性 Fragment、Suspense、Portal

語言: CN / TW / HK

theme: channing-cyan

「這是我參與2022首次更文挑戰的第1天,活動詳情檢視:2022首次更文挑戰」。

前言

vue3中新增了一些功能來解決vue2中那些戳中開發人員痛楚的詬病。同時,也對vue2中效能進行了優化。本文帶你一起探討vue3中新增的FragmentTeleportSuspense的使用方法。

Fragment(碎片化節點)

不知道各位有沒有在vue2中遇到過下圖中的報錯資訊:

企業微信截圖_16365326642677.png 這是vue2丟擲的錯誤提示。意思是說元件只能有一個根元素。當我們新建一個vue頁面時,通常會有多個不同的元素節點。我們會在最外層包裹一個div來使其讓它成為這個頁面的根節點。但這並不友好。有時候我們並不需要這個div元素。

vue3中解決了這個問題。vue3中新增了一個類似dom的標籤元素<Fragment></Fragment>。如果在vue頁面中有多個元素節點。那麼編譯時vue會在這些元素節點上新增一個<Fragment></Fragment>標籤。並且該標籤不會出現在dom樹中。

image.png

Suspense(非同步元件)

vue3中提供一個<Suspense></Suspense>元件用於控制非同步元件。

```javascript //建立一個非同步元件

用`Suspense`包裹非同步元件 `async-component`html 上面的非同步元件使用了定時器,3秒後顯示該元件 我們可以通過`defineAsyncComponent`提供一系列的引數來定義非同步元件javascrpit import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent({ // 工廠函式 loader: () => import('./Foo.vue'), // 載入非同步元件時要使用的元件 loadingComponent: LoadingComponent, // 載入失敗時要使用的元件 errorComponent: ErrorComponent, // 在顯示 loadingComponent 之前的延遲 | 預設值:200(單位 ms) delay: 200, // 如果提供了 timeout ,並且載入元件的時間超過了設定值,將顯示錯誤元件 // 預設值:Infinity(即永不超時,單位 ms) timeout: 3000, // 定義元件是否可掛起 | 預設值:true suspensible: false, / * * @param {} error 錯誤資訊物件 * @param {} retry 一個函式,用於指示當 promise 載入器 reject 時,載入器是否應該重試 * @param {} fail 一個函式,指示載入程式結束退出 * @param {} attempts 允許的最大重試次數 */ onError(error, retry, fail, attempts) { if (error.message.match(/fetch/) && attempts <= 3) { // 請求發生錯誤時重試,最多可嘗試 3 次 retry() } else { // 注意,retry/fail 就像 promise 的 resolve/reject 一樣: // 必須呼叫其中一個才能繼續錯誤處理。 fail() } } }) `` 當配置項中的suspensible為true時,被Suspense`包裹的非同步元件將會被控制

Portal(傳送門)

在vue2中我們可能會使用例如element-ui,iview等元件庫,有時候我們會發現這些ui元件庫中的某些元件渲染層級並不包含在vue dom中。如 modal toast等元件的層級就在vue dom 之外。這種在vue之外的層級方便我們進行全域性處理和管理。vue3中提供一對<teleport ></teleport>用於移動dom的層級 ```javascrpit

Hello Async Component

// 元件a const { createApp } = Vue const componentA = { template: <com-b><com-b/><div class="i-can-fly">我能瞬間移動</div> } const componentB ={ template: <div class="i-can-fly">我能飛</div> } const app = createApp({}) app.component('com-b',componentB) app.component('com-a',componentA) app.mount('#app') 此時我們開啟控制檯檢視元素 ![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e5a7ea58cdd84560965b290815a35e62~tplv-k3u1fbpfcp-watermark.image?) 渲染的結果如下。然後我們修改程式碼新增`teleport`標籤javascrpit

<----...--->

`` 此時我們發現元件B已經不在app中了。而是出現在了以類選擇器為i-can-fly`的div中。

image.png

值得注意的是 teleport標籤上的to引數表示要將包裹的內容所移動到的位置。

最後

文章若有不足之處,還請大家批評指出。

感謝您觀看此篇文章 希望能給個👍評論收藏三連!你的點贊就是我寫作的動力。