Skip to main content
Практика завдань

Асинхронні компоненти та затримка в Vue.js

Асинхронні компоненти

Асинхронні компоненти завантажуються за запитом (ліниве завантаження), що зменшує початковий розмір пакету. Vue надає defineAsyncComponent для цієї мети.


defineAsyncComponent

typescript
import { defineAsyncComponent } from 'vue' // Основний асинхронний компонент const AsyncModal = defineAsyncComponent( () => import('./components/HeavyModal.vue') ) // З параметрами const AsyncDashboard = defineAsyncComponent({ loader: () => import('./components/Dashboard.vue'), loadingComponent: LoadingSpinner, errorComponent: ErrorDisplay, delay: 200, // Затримка перед показом завантаження (мс) timeout: 10000, // Таймаут перед показом помилки (мс) })
vue
<template> <!-- Завантажується лише під час рендерингу --> <AsyncModal v-if="showModal" /> <AsyncDashboard /> </template>

Suspense

<Suspense> — вбудований компонент для обробки асинхронних залежностей — він показує резервний контент, поки асинхронні компоненти або асинхронна ініціалізація завантажуються.

vue
<template> <Suspense> <!-- Слот за замовчуванням: асинхронний контент --> <template #default> <AsyncDashboard /> </template> <!-- Резервний слот: показується під час завантаження --> <template #fallback> <LoadingSpinner /> </template> </Suspense> </template>

Асинхронна ініціалізація

Компоненти з асинхронною setup працюють з <Suspense>:

vue
<!-- UserProfile.vue --> <script setup> // Це робить компонент асинхронним — потрібен батьківський Suspense const response = await fetch('/api/user/1') const user = await response.json() </script> <template> <div> <h1>{{ user.name }}</h1> <p>{{ user.email }}</p> </div> </template>
vue
<!-- Parent.vue --> <template> <Suspense> <UserProfile /> <template #fallback> <p>Завантаження користувача...</p> </template> </Suspense> </template>

Події Suspense

vue
<Suspense @pending="onPending" @resolve="onResolve" @fallback="onFallback" > <AsyncComponent /> <template #fallback> <LoadingSpinner /> </template> </Suspense>

Вкладений Suspense

vue
<Suspense> <template #default> <Dashboard> <!-- Внутрішній Suspense для незалежного завантаження --> <Suspense> <template #default><SlowWidget /></template> <template #fallback><WidgetSkeleton /></template> </Suspense> </Dashboard> </template> <template #fallback> <DashboardSkeleton /> </template> </Suspense>

Комбінування з Vue Router

vue
<template> <RouterView v-slot="{ Component }"> <Suspense> <template #default> <component :is="Component" /> </template> <template #fallback> <PageLoading /> </template> </Suspense> </RouterView> </template>

Обробка помилок

vue
<script setup> import { onErrorCaptured, ref } from 'vue' const error = ref<Error | null>(null) onErrorCaptured((err) => { error.value = err return false // Запобігти поширенню }) </script> <template> <div v-if="error">Помилка: {{ error.message }}</div> <Suspense v-else> <AsyncComponent /> <template #fallback><Loading /></template> </Suspense> </template>

Важливо:

Використовуйте defineAsyncComponent для розподілу коду — завантажуйте важкі компоненти за запитом. Використовуйте <Suspense> для показу станів завантаження для асинхронних компонентів та компонентів з асинхронною setup(). Поєднуйте обидва з Vue Router для розподілу коду на рівні маршруту. Suspense все ще є експериментальним у Vue 3, але широко використовується.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань