Komponent Vue Suspense
z domyślnymi slotami i slotami #fallback, asynchroniczne ładowanie komponentów oraz zagnieżdżone Suspense.
Komponent Vue Suspense to bezpłatna lekcja Vue Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Vue Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Vue Academy zawiera 4 lekcji w sumie.
Jaki problem rozwiązuje Suspense
Suspense to wbudowany komponent Vue, który koordynuje stany ładowania komponentów mających asynchroniczne zależności.
Bez niego każdy komponent asynchroniczny zarządza własnym wskaźnikiem ładowania. Dzięki Suspense deklaruje się jedną granicę, która czeka na całą zagnieżdżoną pracę asynchroniczną i wyświetla pojedynczy element zastępczy do czasu zakończenia wszystkich operacji.
Dwa sloty: default i fallback
Suspense udostępnia dwa nazwane sloty:
- default — rzeczywista zawartość, która może zawierać komponenty asynchroniczne lub asynchroniczne
setup() - fallback — element wyświetlany podczas rozwiązywania slotu default
Gdy wszystkie zależności asynchroniczne zostaną rozstrzygnięte, Vue zastępuje element fallback właściwą zawartością.
<template>
<Suspense>
<template #default>
<UserDashboard />
</template>
<template #fallback>
<div class="spinner">Loading dashboard...</div>
</template>
</Suspense>
</template>Async setup() jako zależność
Komponent staje się zależnością asynchroniczną, gdy jego funkcja setup() jest zadeklarowana jako async i oczekuje na wynik jakiejś operacji. Vue śledzi zwróconą obietnicę.
Odpowiednikiem <script setup> jest użycie najwyższego poziomu await bezpośrednio wewnątrz bloku.
<script setup>
import { ref } from 'vue'
// Top-level await makes this an async dependency of Suspense
const res = await fetch('/api/profile')
const profile = ref(await res.json())
</script>
<template>
<h1>Welcome, {{ profile.name }}</h1>
</template>Komponenty asynchroniczne również się liczą
Komponenty utworzone za pomocą defineAsyncComponent są również śledzone przez Suspense. Element fallback pozostaje widoczny do czasu rozstrzygnięcia dynamicznego import().
Pozwala to wydzielać ciężkie komponenty do osobnych fragmentów kodu bez tworzenia interfejsu ładowania dla każdego komponentu.
<script setup>
import { defineAsyncComponent } from 'vue'
const Chart = defineAsyncComponent(() =>
import('./HeavyChart.vue')
)
</script>
<template>
<Suspense>
<Chart />
<template #fallback>Preparing chart...</template>
</Suspense>
</template>Wspólne oczekiwanie na wiele asynchronicznych dzieci
Jeśli slot default zawiera kilka zależności asynchronicznych, Suspense czeka na rozwiązanie wszystkich, zanim wyświetli zawartość.
Zapobiega to przesuwaniu układu, gdy komponenty pojawiają się pojedynczo.
<template>
<Suspense>
<div>
<UserStats /> <!-- async setup -->
<RecentOrders /> <!-- async setup -->
<Recommendations /> <!-- async component -->
</div>
<template #fallback>
<PageSkeleton />
</template>
</Suspense>
</template>Przechwytywanie odrzuceń za pomocą onErrorCaptured
Jeśli asynchroniczny setup() zostanie odrzucony (na przykład z powodu nieudanego pobierania), błąd propaguje się do najbliższego hooka onErrorCaptured w komponencie nadrzędnym.
Samo Suspense nie renderuje błędów, dlatego należy połączyć je z granicą błędów.
<script setup>
import { ref, onErrorCaptured } from 'vue'
const error = ref(null)
onErrorCaptured((err) => {
error.value = err
return false // stop the error from propagating further
})
</script>Wzorzec granicy błędów i Suspense
Typowy wzorzec produkcyjny umieszcza Suspense wewnątrz komponentu granicy błędów. onErrorCaptured zwraca false, aby zatrzymać propagację i zamiast tego wyświetlić interfejs błędu.
<script setup>
import { ref, onErrorCaptured } from 'vue'
const err = ref(null)
onErrorCaptured((e) => { err.value = e; return false })
</script>
<template>
<p v-if="err">Failed to load: {{ err.message }}</p>
<Suspense v-else>
<ProfilePanel />
<template #fallback>Loading...</template>
</Suspense>
</template>Zdarzenia pending i resolve
Suspense emituje zdarzenia cyklu życia, których można nasłuchiwać:
- @pending — wywoływane przy przejściu do stanu oczekiwania (ładowania)
- @resolve — wywoływane po zakończeniu rozwiązywania slotu default
- @fallback — wywoływane po wyświetleniu zawartości fallbacku
Przydatne w analityce lub na paskach postępu.
<template>
<Suspense @pending="onPending" @resolve="onResolve">
<RouteView />
<template #fallback>Loading route...</template>
</Suspense>
</template>Właściwość timeout dla opóźnionego fallbacku
Właściwość timeout (w milisekundach) opóźnia wyświetlenie fallbacku. Jeśli operacja asynchroniczna zakończy się przed upływem limitu, fallback w ogóle się nie pojawi.
Zapobiega to mignięciu spinnera przy szybkich odpowiedziach.
<template>
<!-- Only show fallback if loading exceeds 200ms -->
<Suspense :timeout="200">
<FastPanel />
<template #fallback>Loading...</template>
</Suspense>
</template>Suspense z routerem i przejściami
Suspense współpracuje z RouterView i Transition, umożliwiając animowanie asynchronicznych zmian tras. Kolejność ma znaczenie: Transition opakowuje Suspense, które z kolei opakowuje komponent obsługujący trasę.
<template>
<RouterView v-slot="{ Component }">
<Transition mode="out-in">
<Suspense>
<component :is="Component" />
<template #fallback>Loading page...</template>
</Suspense>
</Transition>
</RouterView>
</template>Kiedy NIE używać Suspense
Należy unikać Suspense w przypadku danych pobieranych ponownie, gdy komponent pozostaje zamontowany — mechanizm ten obsługuje tylko początkowe rozwiązanie asynchroniczne. W przypadku bieżących stanów ładowania (paginacja, ponowne pobieranie) należy zamiast tego użyć zwykłego reaktywnego refa loading.
<script setup>
import { ref } from 'vue'
const loading = ref(false)
async function loadMore() {
loading.value = true
await fetchNextPage()
loading.value = false
}
</script>Szybki test
Sprawdź swoją wiedzę na temat Suspense.
Podsumowanie
Dowiedział się Pan, jak Suspense koordynuje zależności asynchroniczne:
- slot default zawiera treści asynchroniczne (asynchroniczny setup lub komponenty asynchroniczne)
- slot fallback jest wyświetlany podczas ładowania
- mechanizm czeka na wszystkie asynchroniczne komponenty podrzędne, zanim wyświetli zawartość
- odrzucenia propagują się do
onErrorCapturedw granicy nadrzędnej timeoutzapobiega mignięciu spinnera, a zdarzenia takie jak@resolvepomagają w analityce
Często zadawane pytania
Czy lekcja „Komponent Vue Suspense” jest bezpłatna?
Tak — pełny tekst „Komponent Vue Suspense” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Vue Academy, przejdź na CoddyKit PRO. Kurs Vue Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Komponent Vue Suspense”?
z domyślnymi slotami i slotami #fallback, asynchroniczne ładowanie komponentów oraz zagnieżdżone Suspense. Ćwiczysz Vue Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Vue Academy?
Nie wymagamy żadnego doświadczenia. Vue Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Komponent Vue Suspense”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Vue Academy?
Tak. Każda lekcja Vue Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Komponent Vue Suspense
- Komponenty asynchroniczne z defineAsyncComponent
- Strumieniowanie SSR z renderToWebStream
- Strategie odroczonej hydratacji