異步組件
簡(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ò)誤

提示我們需要使用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ò)誤信息




和其他組件組合
我們常常會(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>