异步组件需要被渲染的时候才会从服务器端请求组件的相关 js,而且会把结果缓存起来供未来重新渲染。
采用异步的方式加载组件,可以有效地解决项目打包时组件过大的问题;同时还可以提高性能,使用异步组件的加载方式,只有在该异步组件被触发的时候,才会加载对应的组件,而不是一次性加载所有的组件。
在 Vue2 中,声明一个异步组件:
<template>
<div>
<h1>Async Components</h1>
<p>异步组件测试</p>
<AsyncComponent></AsyncComponent>
</div>
</template>
<script>
// 区别的重点!!!
const AsyncComponent = () => import('@/components/AsyncComponent.vue')
export default {
name: 'async-components',
components:{
'AsyncComponent': AsyncComponent
}
};
</script>
在 Vue3 中,需要使用辅助函数 defineAsyncComponent 来进行显式声明:
<template>
<div>
<h1>Async Components</h1>
<p>异步组件测试</p>
<AsyncComponent></AsyncComponent>
</div>
</template>
<script>
// 区别的重点!!!
const AsyncComponent = defineAsyncComponent(() => import('@/components/AsyncComponent.vue'))
export default {
name: 'async-components',
components:{
'AsyncComponent': AsyncComponent
}
};
Vue3 引入 defineAsyncComponent 辅助函数的原因:
在 Vue 3 中,由于函数组件被定义为纯函数,异步组件定义需要通过将其包装在一个新的 defineAsyncComponent helper 中来显式定义
在 Vue2 中,异步组件的声明中更高级的声明方式:
const AsyncComponent = {
// 加载异步组件时要使用的组件
component: () => import('./AsyncComponent .vue'),
// 在显示 LoadingComponent 之前的延迟 | 默认值:200 ms
delay: 200,
// 如果提供了 timeout,并且加载组件的时间超过了设定值,将显示错误组件
timeout: 3000,
// 错误组件
error: ErrorComponent,
// 加载组件
loading: LoadingComponent
}
同样的,在 Vue3 中也可以这样使用高级方式声明异步组件,只是需要将 component 改为 loader 即可:
const AsyncComponent = defineAsyncComponent({
loader: () => import('./AsyncComponent .vue'),
delay: 200,
timeout: 3000,
error: ErrorComponent,
loading: LoadingComponent
})
此外,Vue3 的异步组件加载函数将不再接收 resolve 和 reject 参数,而且必须始终返回 promise
// 2.x version
const oldAsyncComponent = (resolve, reject) => {
/* ... */
}
// 3.x version
const asyncComponent = defineAsyncComponent(
() =>
new Promise((resolve, reject) => {
/* ... */
})
)
也就是说,工厂函数接收 resolve 回调的方式定义异步组件在 Vue 3.x 不能使用了:
export default {
components: {
asyncComponent : resolve => require(['@/components/asyncComponent .vue'], resolve)
},
}
Vue Router 支持一个类似的机制来异步加载路由组件,也就是俗称的懒加载。尽管类似,但是这个功能和 Vue 所支持的异步组件是不同的。当用 Vue Router 配置路由组件时,你不应该使用 defineAsyncComponent
路由懒加载写法:
// router/index.js
const routes = [
{
path: '/async-component',
name: 'asyncComponent',
component: () =>
import(
/* webpackChunkName: "asyncComponent" */ '@/components/async-component.vue'
)
}
];
异步组件的写法:
<template>
<div>
<h1>Async Components</h1>
<p>异步组件测试</p>
<AsyncComponent></AsyncComponent>
</div>
</template>
<script>
const AsyncComponent = defineAsyncComponent(() => import('@/components/AsyncComponent.vue'))
export default {
name: 'async-components',
components:{
'AsyncComponent': AsyncComponent
}
};