異步組件與Suspense

異步組件

簡(jiǎn)介

就像路由中的異步加載一樣,組件也能異步加載。不像v-if中已經(jīng)提前加載好的,異步組件只有在需要時(shí)才加載。

基本用法

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() => {
  return new Promise((resolve, reject) => {
    // ...從服務(wù)器獲取組件
    resolve(/* 獲取到的組件 */)
  })
})
// ... 像使用其他一般組件一樣使用 `AsyncComp`

defineAsyncComponent 方法接收一個(gè)返回 Promise 的加載函數(shù)。這個(gè) Promise 的 resolve 回調(diào)方法應(yīng)該在從服務(wù)器獲得組件定義時(shí)調(diào)用。你也可以調(diào)用 reject(reason)表明加載失敗。

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
)

如上,ES模塊動(dòng)態(tài)導(dǎo)入也會(huì)返回一個(gè) Promise,所以多數(shù)情況下我們會(huì)將它和 defineAsyncComponent搭配使用。

  • 全局注冊(cè)
    與普通組件一樣,異步組件可以使用 app.component() 全局注冊(cè):
app.component('MyComponent', defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
))

加載與錯(cuò)誤狀態(tài)

defineAsyncComponent的其他參數(shù)能夠支持更高級(jí)的用法

const AsyncComp = defineAsyncComponent({
  // 加載函數(shù)
  loader: () => import('./Foo.vue'),

  // 加載異步組件時(shí)使用的組件
  loadingComponent: LoadingComponent,
  // 展示加載組件前的延遲時(shí)間,默認(rèn)為 200ms
  delay: 200,

  // 加載失敗后展示的組件
  errorComponent: ErrorComponent,
  // 如果提供了一個(gè) timeout 時(shí)間限制,并超時(shí)了
  // 也會(huì)顯示這里配置的報(bào)錯(cuò)組件,默認(rèn)值是:Infinity
  timeout: 3000
})

異步組件可以搭配內(nèi)置的 <Suspense> 組件一起使用。

Suspense

<Suspense>
  <!-- 具有深層異步依賴的組件 -->
  <Dashboard />

  <!-- 在 #fallback 插槽中顯示 “正在加載中” -->
  <template #fallback>
    Loading...
  </template>
</Suspense>

<Suspense>組件有兩個(gè)插槽:#default#fallback。兩個(gè)插槽都只允許一個(gè)直接子節(jié)點(diǎn)。
和異步組件的效果類似,在#default中內(nèi)容未異步加載完成時(shí),默認(rèn)將顯示#fallback中的內(nèi)容。

首先在子組件中,有元素的數(shù)據(jù)需要異步獲取

<template>
<div>
    <h1>name:{{ user.name }}</h1>
    <h1>age:{{ user.age }}</h1>
</div>
</template>

<script >
export default{
    async setup(){
        const fetchUser = ()=>{
            return new Promise((resolve,reject) => {
                setTimeout(()=>{
                    resolve({name:'Mike',age:'20'})
                },2000)
            })
        }

        const user = await fetchUser()

        return {user};
    }
}

</script>

而如果在父組件中直接使用子組件,那么會(huì)出現(xiàn)如下錯(cuò)誤

image.png

提示我們需要使用Suspense,如下:

<template>
    <Suspense>
         //這里可以使用template包裹,并加上#default標(biāo)記
        <User/>
        <template #fallback>
            Loading...
        </template>
    </Suspense>

</template>

<script setup>
import User from "./User.vue";
</script>

獲取失敗也可以展示失敗頁(yè)面效果,那就需要在父組件中使用onErrorCaptured鉤子收集錯(cuò)誤信息

image.png
image.png
image.png
image.png

和其他組件組合

我們常常會(huì)將 <Suspense><Transition>``<KeepAlive> 等組件結(jié)合。要保證這些組件都能正常工作,嵌套的順序非常重要。
另外,這些組件都通常與Vue Router中的 <RouterView> 組件結(jié)合使用。

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

          <!-- 加載中狀態(tài) -->
          <template #fallback>
            正在加載...
          </template>
        </Suspense>
      </KeepAlive>
    </Transition>
  </template>
</RouterView>

Vue Router使用動(dòng)態(tài)導(dǎo)入對(duì)懶加載組件進(jìn)行了進(jìn)行了內(nèi)置支持。注意:這些與異步組件不同,目前它們不會(huì)觸發(fā)<Suspense>。但是,它們?nèi)匀豢梢杂挟惒浇M件作為后代,這些組件可以照常觸發(fā)<Suspense>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容