Rozdział 11 z 11

Kurs Vue 3: przejścia i animacje z Transition i TransitionGroup

zweryfikowano 2 września 2026 · 5 min

Szybka odpowiedź

<Transition> animuje pojedynczy element przy pojawieniu się i zniknięciu, <TransitionGroup> animuje listę. Vue nakłada klasy CSS, a o efekcie decyduje twój arkusz stylów. Uwaga: w Vue 3 klasy początkowe to -enter-from i -leave-from, a nie -enter i -leave jak w Vue 2.

Na koniec tego rozdziału, będziesz umieć animować pojawianie się, znikanie i przesuwanie elementów, bez żadnej biblioteki.

Element, który pojawia się od razu, sprawia wrażenie przeskoku. Vue dostarcza dwa wbudowane komponenty, <Transition> i <TransitionGroup>, które w odpowiednim momencie nakładają klasy CSS, aby animować pojawianie się i znikanie. Żadnej biblioteki do instalowania.

Zasada działania

Owiń w <Transition> element, którego wyświetlanie zależy od warunku. Vue samo go nie animuje: dodaje i usuwa klasy, a o efekcie decyduje twój CSS.

Sześć klas obejmuje pełny cykl.

css
/* wejście */
.v-enter-from     /* stan początkowy, nakładany tuż przed wstawieniem */
.v-enter-active   /* przez całe wejście: tutaj trafia transition */
.v-enter-to       /* stan docelowy */

/* wyjście */
.v-leave-from     /* stan początkowy wyjścia */
.v-leave-active   /* przez całe wyjście */
.v-leave-to       /* stan końcowy, tuż przed usunięciem z DOM */

Przedrostek v- należy do przejścia bez nazwy. Przy name="fade" klasy stają się fade-enter-from, fade-enter-active i tak dalej.

Pułapka kodu znalezionego w sieci

W Vue 2 klasy początkowe nazywały się .fade-enter i .fade-leave, bez przyrostka. Vue 3 zmieniło ich nazwy na -enter-from i -leave-from. Przykład skopiowany ze starego artykułu nie wywoła więc żadnej animacji przy wejściu, bez najmniejszego komunikatu o błędzie. Jeśli twoje przejście nic nie robi, sprawdź najpierw ten punkt.

Animowanie dostępności

W ProductDisplay.vue komunikat o stanie magazynu przełącza się między dwoma akapitami zależnie od wariantu pod kursorem. Owiń je:

src/components/ProductDisplay.vue
<Transition name="fade" mode="out-in">
  <p v-if="inStock" key="in">En stock</p>
  <p v-else key="out">En rupture</p>
</Transition>

Następnie opisz efekt w arkuszu stylów, tak jak w rozdziale o klasach i stylach:

src/assets/boutique.css
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
  transform: translateY(-10px);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity .3s ease, transform .3s ease;
}

Najedź na kolorowe kropki: komunikat przenika zamiast przeskakiwać.

mode="out-in" czeka, aż stary element zniknie, zanim wstawi nowy. Bez niego oba akapity współistnieją przez ułamek sekundy i nakładają się na siebie.

Co przyjmuje Transition

Tylko jeden element naraz. To główne ograniczenie: <Transition> animuje pojedyncze dziecko, a nie listę.

Uruchamia się w trzech sytuacjach: przy v-if, przy v-show albo przy zmianie komponentu przez <component :is>. Aby wymusić przejście między dwoma elementami tego samego typu, nadaj im różne key, jak powyżej.

Animowanie listy

Do listy potrzebny jest <TransitionGroup>. Dwie różnice: przyjmuje wiele dzieci i sam renderuje element kontenera, jeśli poprosisz o to atrybutem tag.

W ReviewList.vue zastąp <ul>:

src/components/ReviewList.vue
<template>
  <div class="review-container">
    <h3>Avis</h3>
    <TransitionGroup name="liste" tag="ul">
      <li v-for="review in reviews" :key="review.id">
        {{ review.name }} a mis {{ review.rating }} étoiles
        <br>
        « {{ review.review }} »
      </li>
    </TransitionGroup>
  </div>
</template>

Każde dziecko potrzebuje unikalnego i stabilnego key. Indeks tutaj nie wystarczy: zmienia się przy każdym wstawieniu, a Vue nie wiedziałoby już, który element jest nowy. Nadajmy każdej opinii identyfikator w chwili dodania:

src/components/ProductDisplay.vue
<script setup>
function addReview(review) {
  reviews.value.push({ ...review, id: crypto.randomUUID() })
}
</script>

crypto.randomUUID() jest dostępne we wszystkich aktualnych przeglądarkach, na stronach serwowanych po HTTPS lub z localhost.

CSS zyskuje jeszcze jedną klasę, -move, która animuje przesuwanie pozostałych elementów, gdy sąsiad znika:

src/assets/boutique.css
.liste-enter-from,
.liste-leave-to {
  opacity: 0;
  transform: translateX(24px);
}

.liste-enter-active,
.liste-leave-active,
.liste-move {
  transition: all .3s ease;
}

Dodaj kilka opinii: każda wjeżdża, a pozostałe płynnie się porządkują.

Wyjście i przesunięcie

Żeby -move działało przy usuwaniu, znikający element musi zostać wyjęty z układu, inaczej pozostałe ruszą się dopiero po zakończeniu jego animacji. Dodaj position: absolute do klasy -leave-active, gdy twoje elementy można usuwać.

Animowanie przy pierwszym wyświetleniu

Domyślnie przy pierwszym renderowaniu nic nie jest animowane. Zmienia to atrybut appear:

html
<Transition name="fade" appear>
  <p>Visible dès le chargement, en fondu</p>
</Transition>

Animacje CSS i haki

transition to nie jedyna opcja: działa też animacja CSS animation, nałożona na klasę -enter-active.

Aby sterować biblioteką animacji w JavaScripcie, <Transition> emituje zdarzenia na każdym etapie:

html
<Transition
  :css="false"
  @before-enter="avantEntree"
  @enter="entree"
  @after-enter="apresEntree"
  @leave="sortie"
>
  <p v-if="visible">Contenu</p>
</Transition>

Przy :css="false" Vue przestaje zarządzać klasami i oddaje ci stery. Funkcje enter i leave otrzymują wtedy element oraz wywołanie zwrotne done, które trzeba wywołać po zakończeniu animacji:

javascript
function entree(el, done) {
  // animacja przy użyciu wybranej biblioteki
  done()
}

Ruch nie zawsze jest pożądany

Część osób wyłącza animacje na poziomie systemu, zwłaszcza po to, by uniknąć mdłości wywołanych ruchem. Uszanuj to ustawienie:

src/assets/boutique.css
@media (prefers-reduced-motion: reduce) {
  .fade-enter-active,
  .fade-leave-active,
  .liste-enter-active,
  .liste-leave-active,
  .liste-move {
    transition: none;
  }
}

Interfejs pozostaje sprawny, znika tylko animacja.

To koniec kursu

Twoja aplikacja pokazuje produkt i jego warianty, obsługuje koszyk, waliduje formularz i animuje zmiany stanu. Przeszedłeś reaktywność, dyrektywy, komponenty, propsy, zdarzenia i przejścia: tyle, by na co dzień czytać i pisać w Vue.

Dalej dwie drogi. Współdzielenie stanu między odległymi komponentami z Pinią, gdy przekazywanie zdarzeń w górę staje się uciążliwe. Oraz routing z Vue Routerem, gdy tylko aplikacja ma kilka stron.

W Options API

<Transition> i <TransitionGroup> są komponentami wbudowanymi: zapisuje się je dokładnie tak samo. Zmieniają miejsce tylko funkcje haków JavaScript, które trafiają do opcji methods.

ĆwiczenieDodaj przejście na obrazku produktu, aby przenikał przy zmianie wariantu. Będzie potrzebny key powiązany z wybranym wariantem.

Częste błędy

Używanie klas z Vue 2 .fade-enter i .fade-leave zostały przemianowane na -enter-from i -leave-from. Nic się nie animuje i nie pojawia się żaden błąd.
Pominięcie mode="out-in" Bez niego element wchodzący i wychodzący współistnieją przez ułamek sekundy i nakładają się na siebie.
Użycie indeksu jako klucza w TransitionGroup Vue nie odróżnia już nowego elementu od pozostałych i animuje niewłaściwy wpis.
Testowanie animowanego komponentu w Vue Test Utils Przejścia są domyślnie zastępowane stubami. Przekaż global: { stubs: { 'transition-group': false } }, aby zobaczyć prawdziwy render.
Newsletter

Nowe testy, poradniki i projekty, e-mailem.

Powtarzalne testy, wersjonowany kod, datowane wyniki. Nigdy spamu.