1、导入异步组件
方式一:
若组件setup返回的是一个Promise对象,则该组件默认为异步组件,导入时使用defineAsyncComponent异步导入/import同步导入都行
方式二:
手动定义异步组件并导入
方式一:
const Hel=defineAsyncComponent(()=> import('./components/HelloWorld.vue'))
在components中配置
方式二:
比如setup中返回一个Promise,则表明该组件就是一个异步组件
setup(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve({
msg:'异步'
})
},2000)
})
}
async setup(){
return {...}
}
方式三:
const AsyncComp = defineAsyncComponent(
() =>
new Promise((resolve, reject) => {
resolve({
template: '<div>I am async!</div>'
})
resolve(组件实例)
})
)
2、使用Suspense悬挂,当异步组件加载完成时,将展示设置的同步内容
异步组件不需要作为 <suspense> 的直接子节点,它可以出现在组件树任意深度的位置,只有所有的后代组件都准备就绪,该内容才会被认为解析完毕。
(1)使用:
<Suspense>
异步内容:
方式一:
<template v-slot:default 简写#default>
<异步组件 />
</template>
方式二:
<component :is="Component"></component>
方式三:
<Dashboard /> 异步组件
同步内容:
<template v-slot:fallback 简写#fallback>
...同步展示内容
</template>
</Suspense>
另一个触发fallback的方式是让后代组件从setup函数中返回一个Promise
export default {
async setup() {
在`setup`内部使用`await`需要非常小心
因为大多数组合式API函数只会在第一个`await`之前工作
const data = await loadData()
// 它隐性地包裹在一个 Promise 内
// 因为函数是 `async` 的
return {
// ...
}
}
}
(2)子组件更新展示fallback时机
一旦<suspense>的default插槽里的内容被解析,则它只有在default根结点被替换的时候才能被再次触发。
而树里的深层嵌套组件不足以让 <suspense> 回到等待状态
如果根结点发生了变化,它会触发pending事件。
默认情况下,它不会更新DOM以展示fallback内容,会继续展示旧的DOM,直到新组件准备就绪。
给Suspense组件属性timeout,这个值是一个毫秒数,告诉 <suspense> 组件多久之后展示fallback,如果为0则表示它在 <suspense> 进入等待状态时会立即显示
(3)事件
pending:首次渲染、根结点发生了变化,
resolve:在default插槽完成新内容的解析之后被触发
fallback:在fallback插槽的内容展示的时候被触发
(4)错误捕捉
errorCaptured 选项
onErrorCaptured() 钩子
(5)和其他内置组件结合
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Transition mode="out-in">
<KeepAlive>
<Suspense>
<!-- 主要内容 -->
<component :is="Component"></component>
<!-- 加载中状态 -->
<template #fallback>
正在加载...
</template>
</Suspense>
</KeepAlive>
</Transition>
</template>
</RouterView>
代码示例:
异步组件:
<template>
<!-- 不用写根标签 -->
<div>{{msg}}</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({ //定义一个组件
name: 'AsyncHelloWorld',
props: { //传递参数,可以添加类型约束
msg: String,
},
setup(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve({
msg:'异步'
})
},2000)
})
}
});
</script>
悬挂使用:
<template>
<div id="nav">
<Suspense>
<template v-slot:default>
<Hel />
</template>
<template v-slot:fallback>
<div>
loading
</div>
</template>
</Suspense>
</div>
<!-- <router-view/> -->
</template>
<script lang='ts'>
// ,ref, reactive
import {defineComponent,ref,reactive,onMounted,watch,shallowRef,shallowReadonly,defineAsyncComponent} from 'vue';
// import Hel from './components/HelloWorld.vue';
const Hel=defineAsyncComponent(()=> import('./components/HelloWorld.vue'));
export default defineComponent({
name:"App",
components:{
Hel,
}
})
</script>