动态组件
概述:
在有一些特殊场景中,我们需要在一些位置根据不同的条件渲染不同的组件。
我们当然可以使用 v-if或者 v-show 将组件一个个写在模板上,但是如果条件越来越复杂,模板上面的判断越来越多,就会降低代码的可阅读性。
Vue 官方提出的动态组件就是为了帮助我们解决组件条件渲染的问题。
代码示例:
基本使用:
<component :is="tabs[currentTab]"></component>
这里的 is 可以是:
- 在
components选项中被注册的组件名 - ES Module 导入的组件对象
- 异步组件
解决组件频繁重新渲染的问题
当组件越来越多时,<component>中映射的组件会被频繁地切换。但是有时候,我们不希望组件频繁地被【重新渲染】
配合另外一个内置组件 <KeepAlive>可以很好地帮我们解决这个问题:
<keep-alive>
<component :is="tabs[currentTab]"></component>
</keep-alive>
补充
关于
<component>元元素请参考:cn.vuejs.org/api/built-i…
异步组件
概述:
异步组件就是在一开始定义的时候不导入,在使用的时候再使用 HTTP 请求渲染的组件。
本质:
异步组件的本质就是一个 ES Module 的动态(组件)导入定义。
如何声明?
- 在 Vue2 中,动态组件直接使用 ES Module 的动态导入即可:
<script>
const Comp = () => import('@/components/Foo.vue');
</script>
- 在 Vue3 中,动态组件需要使用
defineAsyncComponent函数进行定义:
defineAsyncComponent
接收返回 Promise<C> 的回调函数声明:
在 defineAsyncComponent 中传入一个返回 Promise<C>(这里的 C 为组件)的回调函数来声明一个动态组件:
import { defineAsyncComponent } from 'vue';
// 局部声明
const AsyncComp = defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
// ...从服务器获取组件
resolve(/* 获取到的组件 */);
// ... 假如没有获取到,使用 reject 接收兜底的错误组件
reject(/* 兜底错误组件 */);
});
});
// ... 像使用其他一般组件一样使用 `AsyncComp`
// 全局声明
app.defineComponent('AsyncComp', defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
// ...从服务器获取组件
resolve(/* 获取到的组件 */);
// ... 假如没有获取到,使用 reject 接收兜底的错误组件
reject(/* 兜底错误组件 */);
});
}))
接收动态导入声明:
和 Vue2 的语法类似,Vue3 中也可以使用动态导入来进行声明动态组件:
// 局部声明
const MyComponent = defineAsyncComponent(() =>
import('./components/MyComponent.vue')
));
// 全局声明
app.component('MyComponent', defineAsyncComponent(() =>
import('./components/MyComponent.vue')
));
选项精确定义:
异步操作不可避免地会涉及到加载和错误状态,因此 defineAsyncComponent() 也支持在高级选项中处理这些状态 (以官网示例举例):
const AsyncComp = defineAsyncComponent({
// 加载函数
loader: () => import('./Foo.vue'),
// 加载异步组件时使用的组件
loadingComponent: LoadingComponent,
// 展示加载组件前的延迟时间,默认为 200ms
delay: 200,
// 加载失败后展示的组件
errorComponent: ErrorComponent,
// 如果提供了一个 timeout 时间限制,并超时了
// 也会显示这里配置的报错组件,默认值是:Infinity
timeout: 3000
});
配合 <Suspense>使用
异步组件默认就是“suspensible”(有悬念的)的。这意味着如果组件关系链上有一个 <Suspense>,那么这个异步组件就会被当作这个 <Suspense> 的一个异步依赖。在这种情况下,加载状态是由 <Suspense> 控制,而该组件自己的加载、报错、延时和超时等选项都将被忽略。
异步组件也可以通过在选项中指定 suspensible: false 表明不用 Suspense 控制,并让组件始终自己控制其加载状态。