Vue 3 defineAsyncComponent 思考

Vue 3的defineAsyncComponent允许延迟加载组件,提高应用性能。本文介绍了其工作原理,通过示例展示了如何在弹出组件和带有异步设置的组件中使用它,强调了在大型项目中优化页面加载和用户体验的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用 Vue 3 的 defineAsyncComponent 特性可以让我们延迟加载组件。这意味着它们仅在需要时从服务器加载。

什么是defineAsyncComponent

// SOURCE: https://v3.vuejs.org/guide/component-dynamic-async.html
const AsyncComp = defineAsyncComponent(() =>new Promise((resolve, reject) => {resolve({template: '<div>I am async!</div>'})})
) 

defineAsyncComponent 接受一个返回Promise的工厂函数。当我们成功地从服务器获取组件时,这个Promise应该会被 resolve ,如果出现错误则会被 reject

要使用它,我们必须从Vue中导入它,然后才能在脚本的其余部分中使用它。

我们也可以使用工厂函数中的 import ,轻松地从其他文件中添加Vue组件。

import { defineAsyncComponent } from "vue" 

// 简单使用
const LoginPopup = defineAsyncComponent(() => import("./components/LoginPopup.vue")) 

这是使用 defineAsyncComponent 的最简单方法,但我们也可以传入一个完整的选项对象,配置几个更高级的参数。

// with options 
const AsyncPopup = defineAsyncComponent({ loader: () => import("./LoginPopup.vue"),loadingComponent: LoadingComponent, /* 在加载时显示 */errorComponent: ErrorComponent, /* 显示是否有错误 */delay: 1000, /* 在显示加载组件之前延迟毫秒 */timeout: 3000 /* 这个毫秒之后的超时 */
}) 

使用defineAsyncComponent延迟加载弹出组件

在本例中,我们将使用一个由单击按钮触发的登录弹出窗口。

每当我们的应用程序加载时,我们不需要我们的应用程序加载此组件,因为只有在用户执行特定操作时才需要它。

所以这就是我们的登录组件的样子,它只是通过用 position: fixed 将屏幕的其余部分涂黑来创建一个弹出窗口,并且有一些输入和一个提交按钮。

<template> <div class="popup"> <div class="content"> <h4> Login to your account </h4> <input type="text" placeholder="Email" /> <input type="password" placeholder="Password" /> <button> Log in </button> </div> </div>
</template>

<script>
</script>

<style scoped> .popup {position: fixed;width: 100%;top: ; left: ;height: 100%;background-color: rgba(, , , 0.2);display: flex;justify-content: center;align-items: center;
}
.content { min-width: 200px; width: 30%; background: #fff; height: 200px; padding: 10px; border-radius: 5px;
}
input[type="text"], input[type="password"] {border: ;outline: ;border-bottom: 1px solid #eee;width: 80%;margin:auto;font-size: 0.5em;
}
button { border: ; margin-top: 50px; background-color:#8e44ad; color: #fff; padding: 5px 10px; font-size: 0.5em;
} </style> 

而不是像我们通常那样导入它并将其纳入我们的 components 选项中。

<!-- "Standard" way of doing things -->
<template><button @click="show = true"> Login </button><login-popup v-if="show" />
</template>

<script> import LoginPopup from './components/LoginPopup.vue'
export default {components: { LoginPopup },data() {return {show: false}}
} </script> 

我们可以改为使用 defineAsyncComponent 仅在需要时加载它(意味着单击按钮并切换我们的 v-if

<!-- Use defineAsyncComponent-->
<template><button @click="show = true"> Login </button><login-popup v-if="show" />
</template>

<script> import { defineAsyncComponent } from 'vue'
export default {components: { "LoginPopup" : defineAsyncComponent(() => import('./components/LoginPopup.vue'))},data() {return {show: false}}
} </script> 

虽然这在我们使用我们的应用程序时可能看起来是一样的,但让我们检查元素 > 网络来理解这个小而重要的区别。

如果我们不使用 defineAsyncComponent,一旦我们的页面加载,我们就会看到我们的应用程序从服务器上获得LoginPopup.vue。虽然在这个例子中,这可能不是最大的性能问题,但它仍然会减慢加载速度,如果我们有几十个组件这样做,它真的会加起来。

但是,如果我们使用 defineAsyncComponent 查看同一个选项卡,我们会注意到当我们的页面加载时,LoginPopup.vue 不见了,这是因为它还没有加载。

但是一旦我们点击我们的按钮并告诉我们的应用程序显示我们的弹出窗口,这时它就会从服务器加载,我们可以在网络标签中看到它。

这有助于我们实现最佳性能。我们只想在我们的页面初始加载时加载需要的组件。有条件渲染的组件在我们的页面加载时往往是不需要的,所以为什么要让我们的应用程序加载它们呢?

如何使用异步设置功能

无论我们是否使用 defineAsyncComponent 延迟加载,任何具有异步设置功能的组件都必须用 <Suspense> 包装。

简而言之,创建一个异步设置函数是我们的一个选择,可以让我们的组件在渲染前等待一些API调用或其他异步动作。

这是我们具有异步设置的组件。它使用 setTimeout() 模拟 API 调用。

<template> <div class="popup"> <div class="content"><p> Loaded API: {{ article }} </p> <h4> Login to your account </h4> <input type="text" placeholder="Email" /> <input type="password" placeholder="Password" /> <button> Log in </button> </div> </div>
</template>

<script> const getArticleInfo = async () => { // wait 3 seconds to mimic API callawait new Promise(resolve => setTimeout(resolve, 1000));const article = {title: 'My Vue 3 Article',author: 'Matt Maribojoc'}return article
}
export default {async setup() {const article = await getArticleInfo()console.log(article)return {article}}
} </script> 

我们可以在有或没有 defineAsyncComponent 的情况下将它导入到我们的组件中

import LoginPopup from './components/LoginPopup.vue'
// OR 
const LoginPopup = defineAsyncComponent(() => import("./components/LoginPopup.vue")) 

但是如果我们想让它在我们的模板中渲染,我们需要将它包装在一个 Suspense 元素中。这将等待我们的 setup 函数在尝试渲染我们的组件之前解析。

<template><button @click="show = true"> Login </button><Suspense v-if="show"><template #default><login-popup/></template><template #fallback><p> Loading... </p></template></Suspense>
</template> 

这就是结果。用户会看到 “正在加载…”,然后在3秒后(我们的setTimeout的硬编码值),我们的组件将渲染。

默认情况下,我们使用 defineAsyncComponent 定义的所有组件都是可暂停的。

这意味着如果一个组件的父链中有 Suspense,它将被视为该 Suspense 的一个异步依赖。我们的组件的加载、错误、延迟和超时选项将被忽略,而是由 Suspense 来处理。

最后的想法

defineAsyncComponent 在创建有几十个组件的大型项目时是有好处的。当我们进入到懒惰加载组件时,我们可以有更快的页面加载时间,改善用户体验,并最终提高你的应用程序的保留率和转换率。


最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值