应用 Vue 3 的 defineAsyncComponent
个性能够让咱们提早加载组件。这意味着它们仅在须要时从服务器加载。
这是改善初始页面加载的好办法,因为咱们的应用程序将以较小的块加载,而不用在页面加载时加载每个组件。
在本教程中,咱们将学习 defineAsyncComponent
的全部内容,并看一个例子,该例子将一个弹出窗口的加载推延到咱们的应用程序须要的时候。
好了,让咱们开始吧。
什么是defineAsyncComponent
// SOURCE: https://v3.vuejs.org/guide/component-dynamic-async.htmlconst 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 call await 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
在创立有几十个组件的大型项目时是有益处的。当咱们进入到懈怠加载组件时,咱们能够有更快的页面加载工夫,改善用户体验,并最终进步你的应用程序的保留率和转换率。
我想晓得你对这个性能的认识。如果你曾经在你的利用中应用它了,请在上面的评论中通知我。