Skip to content

المكونات الغير متزامنة ​

الاستخدام الأساسي ​

في التطبيقات الكبيرة ، قد نحتاج إلى تقسيم التطبيق إلى أجزاء أصغر وتحميل مكون من الخادم عند الحاجة. لجعل ذلك ممكنًا ، تحتوي Vue على دالة defineAsyncComponent من أجل إنشاء مكون جديد

js
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() => {
  return new Promise((resolve, reject) => {
    // ... تحميل المكون من الخادم
    resolve(/* المكون المُحمل */)
  })
})
// ... استخدم `AsyncComp` مثل مكون عادي

كما تري , defineAsyncComponent يقبل وظيفة أداة التحميل (Loader Function) والتي ترجع وعداً (Promise) . رد الوعد resolve يجب استدعائه عندما يتم استرجاع المكون الخاص بك من الخادم . يمكنك ايضاً إستدعاء الرفض reject(reason) للإشارة إلي فشل التحميل

ES module dynamic import أيضاً يرجع وعداً (Promise), لذالك سنستحدمه في معظم الأوقات مع defineAsyncComponent . تدعم حزم مثل Vite و Webpack البنية أيضًا (وستستخدمها كنقاط تقسيم للحزمة), حتى نتمكن من استخدامه لاستيراد Vue SFCs:

js
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
)

النتيجة AsyncComp هو عبارة عن مكون مُغلف يستدعي وظيفة أداة التحميل فقط عندما يتم عرضها فعليًا على الصفحة. بالإضافة إلي ذالك , سيتم تمرير أي الخاصيات (Props) او منافذ (Slots) إلي المكون الداخلي , لذالك يمكنك استخدام الغُلاف غير المتزامن (Async Wrapper) لأستبدال المكون الأب أثناء التحميل البطئ (Lazy Loading) بسلاسة.

المكونات الغير متزامنة يمكن ان يتم تسجيلها بشكل عام مثل المكونات العادية , بإستخدام app.component():

js
app.component('MyComponent', defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
))

يمكنك أيضاً إستخدام defineAsyncComponent عند تسجيل المكون بشكل محلي:

vue
<script>
import { defineAsyncComponent } from 'vue'

export default {
  components: {
    AdminPage: defineAsyncComponent(() =>
      import('./components/AdminPageComponent.vue')
    )
  }
}
</script>

<template>
  <AdminPage />
</template>

يمكن أيضًا تعريفها مباشرة داخل المكون الرئيسي الخاص بها:

vue
<script setup>
import { defineAsyncComponent } from 'vue'

const AdminPage = defineAsyncComponent(() =>
  import('./components/AdminPageComponent.vue')
)
</script>

<template>
  <AdminPage />
</template>

حالات التحميل و الخطأ ​

تتضمن العمليات غير المتزامنة حتمًا حالات التحميل والخطأ defineAsyncComponent()يدعم التعامل مع هذه الحالات عبر الخيارات المتقدمة:

js
const AsyncComp = defineAsyncComponent({
  // وظيفة أداة التحميل
  loader: () => import('./Foo.vue'),

  // مكون لكي يتم إستخدامه أثناء تحميل المكون غير المتزامن (Async Component)
  loadingComponent: LoadingComponent,
  // التأخير قبل إظهار مكون التحميل. الافتراضي: 200 مللي ثانية.
  delay: 200,

  // مكون لاستخدامه في حالة فشل التحميل
  errorComponent: ErrorComponent,
  // سيتم عرض مكون الخطأ إذا كانت المهلة المقدمة تجاوزت
  // الافتراضي: ما لا نهاية
  timeout: 3000
})

إذا تم توفير مكون التحميل (Loading Component) ، فسيتم عرضه أولاً أثناء تحميل المكون الداخلي. يوجد تأخير افتراضي يبلغ 200 مللي ثانية قبل عرض مكون التحميل - وهذا لأنه في الأنترنت السريع ، قد يتم استبدال حالة التحميل بسرعة كبيرة وينتهي بها الأمر وكأنها وميض.

إذا تم توفير مكون خطأ (Error Component)، فسيتم عرضه عند رفض الوعد الذي أرجعته وظيفة أداة التحميل . يمكنك أيضًا تحديد مهلة (Timeout) لعرض مكون الخطأ عندما يستغرق الطلب وقتًا طويلاً.

Lazy Hydration ​

This section only applies if you are using Server-Side Rendering.

In Vue 3.5+, async components can control when they are hydrated by providing a hydration strategy.

  • Vue provides a number of built-in hydration strategies. These built-in strategies need to be individually imported so they can be tree-shaken if not used.

  • The design is intentionally low-level for flexibility. Compiler syntax sugar can potentially be built on top of this in the future either in core or in higher level solutions (e.g. Nuxt).

Hydrate on Idle ​

Hydrates via requestIdleCallback:

js
import { defineAsyncComponent, hydrateOnIdle } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: hydrateOnIdle(/* optionally pass a max timeout */)
})

Hydrate on Visible ​

Hydrate when element(s) become visible via IntersectionObserver.

js
import { defineAsyncComponent, hydrateOnVisible } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: hydrateOnVisible()
})

Can optionally pass in an options object value for the observer:

js
hydrateOnVisible({ rootMargin: '100px' })

Hydrate on Media Query ​

Hydrates when the specified media query matches.

js
import { defineAsyncComponent, hydrateOnMediaQuery } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: hydrateOnMediaQuery('(max-width:500px)')
})

Hydrate on Interaction ​

Hydrates when specified event(s) are triggered on the component element(s). The event that triggered the hydration will also be replayed once hydration is complete.

js
import { defineAsyncComponent, hydrateOnInteraction } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: hydrateOnInteraction('click')
})

Can also be a list of multiple event types:

js
hydrateOnInteraction(['wheel', 'mouseover'])

Custom Strategy ​

ts
import { defineAsyncComponent, type HydrationStrategy } from 'vue'

const myStrategy: HydrationStrategy = (hydrate, forEachElement) => {
  // forEachElement is a helper to iterate through all the root elements
  // in the component's non-hydrated DOM, since the root can be a fragment
  // instead of a single element
  forEachElement(el => {
    // ...
  })
  // call `hydrate` when ready
  hydrate()
  return () => {
    // return a teardown function if needed
  }
}

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Comp.vue'),
  hydrate: myStrategy
})

الاستخدام مع Suspense ​

المكونات غير متزامنة يمكن ان تستخدم مع المكون المدمج <Suspense> . تم توثيق التفاعل بين <Suspense> و المكونات الغير متزامنة في الفصل المخصص <Suspense>.

المكونات الغير متزامنة has loaded