父组件中,子组件的加载一般是按照先后顺序加载的,子组件加载后才会加载父组件。
一个页面的子组件很多,由于会先加载子组件,那么父组件可能会出现比较长的白屏等待时间
大型项目,可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件Vue 提供defineAsyncComponent
方法:
import { defineAsyncComponent } from 'vue';const AsyncComp = defineAsyncComponent(() => {return new Promise((resolve, reject) => {// ...从服务器获取组件resolve(/* 获取到的组件 */);});
});
使用import导入组件
得到的 AsyncComp
是一个包裹组件,仅在页面需要它渲染时才调用加载函数。另外,它还会将 props 传给内部的组件,所以你可以使用这个异步的包裹组件无缝地替换原始组件,同时实现延迟加载
import { defineAsyncComponent } from 'vue';const AsyncComp = defineAsyncComponent(() => import('./components/MyComponent.vue'));
处理加载与错误的状态
异步操作不可避免地会涉及到加载和错误状态,因此 defineAsyncComponent()
也支持在高级选项中处理这些状态:
const AsyncComp = defineAsyncComponent({// 加载函数 需要返回一个Promise,可以使用动态import的方式,也可以自己new Promise()loader: () => import('./Foo.vue'),// 加载异步组件时使用的组件,该组件会在异步组件加载时显示,如果异步组件加载很快,可能不会出现loading组件loadingComponent: LoadingComponent,// 展示加载组件前的延迟时间,默认为 200msdelay: 200,// 加载失败后展示的组件,可以通过Promise的reject来测试errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制,并超时了// 也会显示这里配置的报错组件,默认值是:Infinitytimeout: 3000
});
如果提供了一个加载组件,它将在内部组件加载时先行显示。在加载组件显示之前有一个默认的 200ms 延迟——这是因为在网络状况较好时,加载完成得太快,导致最终组件的替换可能看起来像是闪烁。
如果提供了一个报错组件,当加载器函数返回的 Promise 被 reject 时,它将被显示出来。你还可以指定一个超时时间,在请求耗时过长时显示报错组件。
动态加载函数方式导入组件
import
默认导入的模块是静态的,如果我们将import
用于动态导入模块,那么将放回一个 Promise,也就是说我们可以在defineAsyncComponent
的加载函数中直接使用import
来动态导入一个模块。
若非必要,请不要滥用动态导入。
import { defineAsyncComponent } from 'vue';
const VmdContent = defineAsyncComponent(() => {return import('@/components/editor/VmdContent.vue');
});
<VmdContent :loading="state.spinning" :result="state.resultData.text"></VmdContent>
示例
new Promise方式
script setup
// app.vue
import { onMounted, defineAsyncComponent } from 'vue';
import Child from './child.vue';
const AsyncChild = defineAsyncComponent(() => new Promise((resolve, reject) => resolve(Child)));
onMounted(() => {console.log('app');
});
<template><AsyncChild />
</template>
对象的方式创建
script setup
// app.vue
import {ref, onMounted, defineAsyncComponent } from 'vue'
import LoadingComp from './LoadingComp.vue' //加载中
import ErrorComp from './ErrorComp.vue' //加载错误
const AsyncChild = defineAsyncComponent({loader: () => (new Promise((resolve, reject) => reject())),loadingComponent: LoadingComp,delay: 200,errorComponent: ErrorComp,timeout: 2000
})
onMounted(() => {console.log('app')
})
let isShowAsyncComp = ref(false)
const loader = () => {isShowAsyncComp.value = true
}
<template><button @click="loader">加载异步组件</button><AsyncChild v-if="isShowAsyncComp" />
</template>