关于 async-components
面向 Vue 开发者的异步组件指南,介绍如何在需要时加载组件,以延后大型或按条件显示的组件,并配置加载中与错误状态。
主要功能
- 01按需加载组件
- 02使用 defineAsyncComponent() 和动态 import()
- 03配置加载与错误组件
- 04控制延迟和超时
适用场景
- 01在模态框打开时再加载
- 02加载按条件渲染的界面
- 03拆分大型组件包
- 04组件加载期间显示状态反馈
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ patternsdev/ skills --skill async-components安装后在 Claude Code 中输入/async-components确认已加载。
详细介绍
异步组件
目录
开发大型 Web 应用时,性能至关重要。页面加载速度和交互元素的响应能力会极大影响用户体验。随着 Web 应用的规模和复杂度不断增加,确保只在需要时加载大型代码包会变得十分重要。Vue 中的异步组件正是为此而生。
组件是构建 UI 的基础模块。通常,使用组件时,即使它们暂时用不到,也会自动加载并解析。
适用场景
- 当组件的代码包较大,且初始页面加载时不需要它们时,使用异步组件
- 这适用于模态框、对话框,或任何根据用户操作有条件渲染的 UI
不适用场景
- 对于较小的组件,如果异步加载的开销(代码块请求、解析)超过了节省代码包的收益,则不适用
- 对于初始渲染时始终可见的组件,异步加载会延迟它们的显示
- 如果组件已经属于主代码块,拆分出来也无法显著减小代码包,则不适用
说明
- 使用
defineAsyncComponent()和动态import()按需加载组件 - 提供
loadingComponent和errorComponent选项,以改善用户体验 - 与
v-if结合使用,仅在实际需要组件时触发异步加载 - 使用
delay和timeout选项,精细控制加载行为
详情
另一方面,异步组件允许我们以这样的方式定义组件:仅在需要它们或满足特定条件时,才加载并解析它们。
假设我们有一个简单的模态框组件,当父组件中的按钮被点击时,该组件就会渲染。Modal.vue 组件文件只包含用于决定模态框外观的模板和样式。
<template>
<div class="modal-mask">
<div class="modal-container">
<div class="modal-body">
<h3>This is the modal!</h3>
</div>
<div class="modal-footer">
<button class="modal-default-button" @click="$emit('close')">OK</button>
</div>
</div>
</div>
</template>
在父级 App 组件中,我们可以渲染模态框组件和一个按钮;点击该按钮时,借助响应式布尔值(showModal)切换模态框组件的可见状态。
<template>
<button id="show-modal" @click="showModal = true">Show Modal</button>
<Modal v-if="showModal" :show="showModal" @close="showModal = false" />
</template>
<script setup>
import { ref } from "vue";
import Modal from "./components/Modal.vue";
const showModal = ref(false);
</script>
从这个示例可以看出,只有在特定情况下才会显示模态框组件——即用户点击 Show Modal 按钮时。尽管如此,与该组件关联的 JavaScript 代码包仍会在整个网页加载时自动加载,甚至早于模态框显示。
在大多数情况下,这没有问题。然而,当模态框的代码包特别大,和/或应用中有许多此类组件时,初始加载时间可能会因此延长。每增加一个代码包,即使其中的组件很少使用,也会延长初始页面的加载时间。
defineAsyncComponent
Vue 借助 defineAsyncComponent() 函数,通过异步加载组件,让我们能够将应用拆分成更小的代码块。
import { defineAsyncComponent } from "vue";
const AsyncComp = defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
// ...load component from the server
resolve(/* loaded component */);
});
});
defineAsyncComponent() 函数接受一个加载器函数,该函数返回一个 Promise,解析后得到导入的组件。不过,我们不必像上面那样定义异步组件函数,也可以利用动态导入异步加载 ECMAScript 模块。
import { defineAsyncComponent } from "vue";
export const AsyncComp = defineAsyncComponent(() =>
import("./components/MyComponent.vue")
);
来看看如何在模态框示例中应用这一方法。我们将创建一个名为 AsyncModal.js 的新文件:
import { defineAsyncComponent } from "vue";
export const AsyncModal = defineAsyncComponent(() => import("./Modal.vue"));
现在,我们将在父级 App 组件中导入并使用异步组件 AsyncModal,替代 Modal 组件。
<template>
<button id="show-modal" @click="showModal = true">Show Modal</button>
<AsyncModal v-if="showModal" :show="showModal" @close="showModal = false" />
</template>
<script setup>
import { ref } from "vue";
import { AsyncModal } from "./components/AsyncModal";
const showModal = ref(false);
</script>
只需做出这一点小小的改动,模态框组件就会异步加载!应用网页初次加载时,Modal 组件的代码包_不再会在页面加载时自动加载_。点击按钮触发模态框显示时,代码包才会在渲染模态框组件的过程中异步加载。
加载和错误 UI
使用 defineAsyncComponent(),Vue 为开发者提供的不仅仅是异步加载组件的方式,还提供了在加载过程中向用户显示反馈以及处理潜在错误的功能。
loadingComponent
有时,我们可能希望在获取组件时向用户提供视觉反馈。为此,defineAsyncComponent() 提供了 loadingComponent 选项,让我们指定一个在加载阶段显示的组件。
import { defineAsyncComponent } from "vue";
import Loading from "./Loading.vue";
export const AsyncModal = defineAsyncComponent({
loader: () => import("./Modal.vue"),
loadingComponent: Loading,
});
模态框组件异步加载时,用户将看到 Loading... 消息。
errorComponent
在某些情况下(例如网络连接不佳),异步组件可能无法加载。defineAsyncComponent() 函数提供了 errorComponent 选项来处理此类情况,让我们可以指定在发生加载错误时显示的组件。
import { defineAsyncComponent } from "vue";
import Loading from "./Loading.vue";
import Error from "./Error.vue";
export const AsyncModal = defineAsyncComponent({
loader: () => import("./Modal.vue"),
loadingComponent: Loading,
errorComponent: Error,
});
模态框组件加载失败时,将显示 Error 组件的模板。
defineAsyncComponent() 函数还接受 delay、timeout、suspensible 和 onError() 等选项,让开发者能够更精细地控制异步加载行为和用户体验。有关这些属性的更多详情,请查看 API 文档。
defineAsyncComponent() 函数可以将 Vue 应用的初始加载拆分成易于管理的代码块,将某些组件的加载推迟到需要时再进行。这有助于缩短页面加载时间并提升应用的整体性能,尤其是在应用包含许多代码包体积较大的组件时。