![Lazy loading کامپوننت ها در Vue با استفاده از defineAsyncComponent](https://static.ardweb.ir/posts/2025/February/cbkmxx3v42ck6w6fw6yzco5r.png)
Lazy loading کامپوننت ها در Vue با استفاده از defineAsyncComponent
استفاده از ویژگی defineAsyncComponent
در Vue 3 به ما اجازه میدهد تا کامپوننتها را به صورت lazy بارگذاری کنیم. به معنی اینکه آنها فقط در صورت نیاز از سرور بارگیری می شوند.
که یک راه عالی برای بهبود بارگیری اولیه صفحه است زیرا برنامه ما به جای بارگیری تک تک اجزا در هنگام بارگیری صفحه، در قطعات کوچکتر بارگذاری می شود.
در این آموزش، ما همه چیز را در مورد defineAsyncComponent
می آموزیم و به مثالی نگاه می کنیم که بارگذاری یک پنجره بازشو را تا زمانی که توسط برنامه ما مورد نیاز باشد به تعویق می اندازد.
![](https://static.ardweb.ir/posts/2025/February/aq4anmp7w286f743qzsvegwl.gif)
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 یک factory function را می پذیرد که یک Promise را برمی گرداند. این Promise باید زمانی برطرف شود که مؤلفه را با موفقیت از سرور دریافت کنیم و اگر مشکلی پیش آمد آن را رد کنیم.
برای استفاده از آن، باید آن را از Vue وارد کنیم و سپس میتوانیم آن را در بقیه اسکریپت استفاده کنیم.
ما همچنین میتوانیم به راحتی اجزای Vue را از فایلهای دیگر با استفاده از وارد کردن داخل factory function خود اضافه کنیم.
import { defineAsyncComponent } from 'vue'
// simple usage
const LoginPopup = defineAsyncComponent(() =>
import('./components/LoginPopup.vue')
)
این سادهترین راه برای استفاده از defineAsyncComponent است، اما میتوانیم یک شیء کامل گزینهای را که چندین پارامتر پیشرفتهتر را پیکربندی میکند، ارسال کنیم.
// with options
const AsyncPopup = defineAsyncComponent({
loader: () => import('./LoginPopup.vue'),
loadingComponent: LoadingComponent /* shows while loading */,
errorComponent: ErrorComponent /* shows if there's an error */,
delay: 1000 /* delay in ms before showing loading component */,
timeout: 3000 /* timeout after this many ms */,
})
من شخصاً بیشتر از دستور اول و کوتاهتر استفاده میکنم و برای اکثر موارد استفاده من کار میکند، اما کاملاً به شما بستگی دارد.
و واقعاً به همین سادگی است، بنابراین بیایید وارد مثال خود شویم.
lazy loading یک کامپوننت پاپ آپ با defineAsyncComponent
برای این مثال، ما با یک پنجره ورود به سیستم کار می کنیم که با کلیک یک دکمه فعال می شود.
ما نیازی نداریم که برنامه ما هر زمان که برنامه ما بارگیری می شود این مؤلفه را بارگیری کند زیرا فقط زمانی لازم است که کاربر یک عمل خاص را انجام دهد.
بنابراین مؤلفه ورود ما به این شکل است، فقط یک پنجره بازشو با سیاه کردن بقیه صفحه با موقعیت ایجاد می کند: ثابت است و دارای چند ورودی و یک دکمه ارسال است.
<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: 0;
left: 0;
height: 100%;
background-color: rgba(0, 0, 0, 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: 0;
outline: 0;
border-bottom: 1px solid #eee;
width: 80%;
margin: 0 auto;
font-size: 0.5em;
}
button {
border: 0;
margin-top: 50px;
background-color:#8e44ad;
color: #fff;
padding: 5px 10px;
font-size: 0.5em;
}
</style>
![](https://static.ardweb.ir/posts/2025/February/djsae5uiua70bnt9c3y64d05.png)
به جای وارد کردن آن و گنجاندن آن در گزینه های اجزای …
<template>
<!-- "Standard" way of doing things -->
<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 ما تغییر میکند)
<template>
<!-- Use defineAsyncComponent -->
<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>
در حالی که ممکن است زمانی که از برنامه خود استفاده می کنیم، یکسان به نظر برسد، اجازه دهید Element > Network
را بررسی کنیم تا این تفاوت کوچک و در عین حال مهم را درک کنیم.
اگر از defineAsyncComponent استفاده نکنیم، به محض اینکه صفحه ما بارگیری می شود، خواهیم دید که برنامه ما LoginPopup.vue را از سرور ما دریافت می کند.
در حالی که در این مثال، ممکن است بزرگترین مشکل عملکرد را ایجاد نکند، اما باز هم کمی سرعت بارگذاری را کاهش میدهد و اگر دهها کامپوننت این کار را انجام میدهند، واقعاً میتواند باعث سنگینی اضافه شود.
![](https://static.ardweb.ir/posts/2025/February/qwtkhez2uwx4b557kjqte2xk.png)
با این حال، اگر با استفاده از defineAsyncComponent به همان برگه نگاه کنیم، متوجه میشویم که وقتی صفحه ما بارگذاری میشود، LoginPopup.vue در جایی دیده نمیشود. دلیلش این است که هنوز بارگذاری نشده است.
![](https://static.ardweb.ir/posts/2025/February/w3lsc09nyv0pyr46opam8gu5.png)
اما هنگامی که روی دکمه خود کلیک می کنیم و به برنامه خود می گوییم که پنجره ما را نشان دهد، آن موقع است که از سرور بارگیری می شود و می توانیم آن را در تب Network ببینیم.
![](https://static.ardweb.ir/posts/2025/February/n13c7k5xkydrwi1tdpcf1dg3.png)
این به ما کمک می کند تا بهترین عملکرد را داشته باشیم.
ما فقط می خواهیم اجزای مورد نیاز در بارگذاری اولیه صفحه خود را بارگیری کنیم. هنگامی که صفحه ما بارگیری می شود، معمولاً مؤلفه هایی که به صورت مشروط رندر می شوند مورد نیاز نیستند، پس چرا برنامه ما را مجبور به بارگیری آنها کنیم؟
نحوه استفاده با یک تابع راه اندازی ناهمزمان
صرف نظر از اینکه بارگذاری را با defineAsyncComponent
به تعویق بیندازیم، هر مؤلفه ای با تابع تنظیم ناهمزمان باید با یک <Suspense>
پیچیده شود.
بیایید به یک مثال نگاه کنیم. این از مقدمه ما بر مؤلفههای تعلیق است که اگر در کارکردهای راهاندازی همگامسازی تازه کار هستید، منبع خوبی است.
به طور خلاصه، ایجاد یک تابع راهاندازی async یکی از گزینههایی است که باید مؤلفه خود را قبل از رندر کردن منتظر برخی از تماسهای API یا سایر اقدامات ناهمزمان کنیم.
در اینجا کامپوننت ما با یک راه اندازی همگام است. این یک تماس API را با یک setTimeout()
تقلید می کند.
<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 قرار دهیم. این منتظر می ماند تا عملکرد راه اندازی ما قبل از تلاش برای رندر کردن مؤلفه ما حل شود.
یکی از ویژگیهای منظم Suspense این است که میتوانیم محتوای بازگشتی را با استفاده از اسلاتها و قالبها نمایش دهیم. محتوای بازگشتی نمایش داده میشود تا زمانی که عملکرد راهاندازی برطرف شود و مؤلفه ما آماده ارائه شود.
توجه داشته باشید که v-if از خود کامپوننت به کامپوننت Suspense ما منتقل میشود، بنابراین همه موارد بازگشتی نمایش داده میشوند.
<template>
<button @click="show = true">Login</button>
<Suspense v-if="show">
<template #default>
<login-popup />
</template>
<template #fallback>
<p>Loading...</p>
</template>
</Suspense>
</template>
این نتیجه کار است. کاربر "loading..." را می بیند و بعد از 3 ثانیه (مقدار سخت کد برای setTimeout ما) component ما رندر می شود.
![](https://static.ardweb.ir/posts/2025/February/fbzp7z114lxqt0adviqbo7qc.gif)
به طور پیش فرض، تمام اجزایی که با استفاده از defineAsyncComponent تعریف می کنیم، قابل تعلیق هستند
به این معنی که اگر در زنجیره اصلی یک جزء، Suspense وجود داشته باشد، به عنوان یک وابستگی ناهمگام آن Suspense در نظر گرفته می شود. گزینههای بارگیری، خطا، تأخیر و زمانبندی مؤلفههای ما نادیده گرفته میشوند و در عوض توسط Suspense مدیریت میشوند.
کلام آخر
defineAsyncComponent می تواند هنگام ایجاد پروژه های بزرگ با ده ها مؤلفه مفید باشد. وقتی به مؤلفههای lazy lading میرسیم، میتوانیم زمان بارگذاری سریعتری داشته باشیم که تجربه کاربر را بهبود میبخشد و در نهایت نرخ نگهداری و تبدیل در برنامه شما را افزایش میدهد.
منبع LearnVue