Kurs Vue.js · Moduł 13: Przejścia i animacje

JavaScript Animation Hooks

3 min czytania
W tej lekcji7

Klasy CSS to "autopilot" animacji - działa świetnie dla prostych przejść. Ale czasem potrzebujesz pełnej kontroli nad animacjami - np. dynamicznie obliczanych wartości, animacji zależnych od danych, albo integracji z bibliotekami JS. W takich przypadkach Vue oferuje JavaScript animation hooks - jak ręczne sterowanie rakietą zamiast automatycznego lotu.

Dostępne hooki

<Transition> emituje zdarzenia na każdym etapie animacji. Możesz na nie nasłuchiwać:

1<Transition
2  :css="false"
3  @before-enter="onBeforeEnter"
4  @enter="onEnter"
5  @after-enter="onAfterEnter"
6  @enter-cancelled="onEnterCancelled"
7  @before-leave="onBeforeLeave"
8  @leave="onLeave"
9  @after-leave="onAfterLeave"
10  @leave-cancelled="onLeaveCancelled"
11>
12  <div v-if="show">...</div>
13</Transition>

Hooki wejścia (enter) - kolejność wywołania

  1. @before-enter(el) - wywoływany zanim element zostanie wstawiony do DOM. Tutaj ustawiasz stan początkowy animacji (np. opacity: 0, scale: 0.5).

  2. @enter(el, done) - wywoływany w następnej klatce po wstawieniu elementu. Tu uruchamiasz właściwą animację. Musisz wywołać done() gdy animacja się zakończy!

  3. @after-enter(el) - wywoływany po zakończeniu animacji (po done()). Tutaj sprzątasz po animacji (usuwasz inline styles itp.).

  4. @enter-cancelled(el) - wywoływany gdy animacja wejścia zostanie przerwana (np. użytkownik szybko toggle'uje element).

Hooki wyjścia (leave) - analogiczna kolejność

  1. @before-leave(el) - stan początkowy wyjścia, element jest jeszcze widoczny
  2. @leave(el, done) - animacja wyjścia, musisz wywołać done()!
  3. @after-leave(el) - cleanup po wyjściu
  4. @leave-cancelled(el) - przerwanie animacji wyjścia (tylko z v-show)

Atrybut :css="false"

Gdy używasz wyłącznie hooków JS, dodaj :css="false" aby Vue nie próbowało stosować klas CSS ani nasłuchiwać na transitionend/animationend:

1<Transition :css="false" @enter="onEnter" @leave="onLeave">
2  <div v-if="show">Panel kontrolny</div>
3</Transition>

Bez tego atrybutu Vue będzie czekało zarówno na callback done(), jak i na zdarzenie CSS transition - co może powodować nieprzewidywalne zachowanie.

Callback done() - kluczowy element

done() jest obowiązkowy w hookach @enter i @leave. Informuje Vue, że animacja się zakończyła i można przejść do następnego kroku:

1function onBeforeEnter(el) {
2  // Stan początkowy - element niewidoczny
3  el.style.opacity = 0
4  el.style.transform = 'translateY(20px)'
5}
6
7function onEnter(el, done) {
8  // Wymuś reflow, aby przeglądarka zarejestrowała stan początkowy
9  el.offsetHeight
10
11  // Uruchom animację
12  el.style.transition = 'all 0.5s ease'
13  el.style.opacity = 1
14  el.style.transform = 'translateY(0)'
15
16  // Powiadom Vue gdy animacja się zakończy
17  el.addEventListener('transitionend', done, { once: true })
18}
19
20function onAfterEnter(el) {
21  // Cleanup - usuń inline transition
22  el.style.transition = ''
23}

Bez wywołania done() Vue nie wie kiedy animacja się zakończyła - w przypadku @leave element nigdy nie zostanie usunięty z DOM.

Praktyczny przykład - animacja zależna od danych

Hooki JS pozwalają na dynamiczne wartości, czego CSS classes nie umożliwiają:

1function onEnter(el, done) {
2  // Dynamiczny kierunek animacji na podstawie danych
3  const direction = el.dataset.direction || 'left'
4  const offset = direction === 'left' ? '-100px' : '100px'
5
6  el.style.opacity = 0
7  el.style.transform = `translateX(${offset})`
8  el.offsetHeight // reflow
9
10  el.style.transition = 'all 0.4s ease-out'
11  el.style.opacity = 1
12  el.style.transform = 'translateX(0)'
13
14  el.addEventListener('transitionend', done, { once: true })
15}

Kiedy używać hooków JS zamiast CSS?

Użyj CSS klasUżyj JS hooków
Proste fade, slideDynamiczne wartości animacji
Stałe czasy trwaniaCzasy zależne od danych
Typowe przejściaIntegracja z GSAP, Anime.js
Większość przypadkówZłożone sekwencje animacji
Kod do tej lekcji: App.vue
1<script setup>
2import { ref } from 'vue'
3
4const showAlert = ref(false)
5
6function onBeforeEnter(el) {
7  el.style.opacity = 0
8  el.style.transform = 'scale(0.5)'
9}
10
11function onEnter(el, done) {
12  // Animacja wejścia bez CSS
13  el.offsetHeight // wymuszenie reflow
14  el.style.transition = 'all 0.6s ease'
15  el.style.opacity = 1
16  el.style.transform = 'scale(1)'
17  el.addEventListener('transitionend', done, { once: true })
18}
19
20function onLeave(el, done) {
21  el.style.transition = 'all 0.4s ease'
22  el.style.opacity = 0
23  el.style.transform = 'scale(0.5) rotate(10deg)'
24  el.addEventListener('transitionend', done, { once: true })
25}
26</script>
27
28<template>
29  <div class="nova-lab">
30    <h1>JavaScript Animation Hooks</h1>
31
32    <button @click="showAlert = !showAlert" class="btn">
33      {{ showAlert ? 'Zamknij alert' : 'Pokaż alert' }}
34    </button>
35
36    <Transition
37      :css="false"
38      @before-enter="onBeforeEnter"
39      @enter="onEnter"
40      @leave="onLeave"
41    >
42      <div v-if="showAlert" class="alert">
43        UWAGA: Wykryto anomalię grawitacyjną w sektorze 7!
44      </div>
45    </Transition>
46  </div>
47</template>
48
49<style scoped>
50.nova-lab {
51  background: #0a0e27;
52  color: #00ff88;
53  min-height: 100vh;
54  padding: 20px;
55  font-family: monospace;
56}
57h1 { color: #00ff88; }
58.btn {
59  background: #e74c3c;
60  color: white;
61  border: none;
62  padding: 10px 20px;
63  border-radius: 8px;
64  cursor: pointer;
65  margin: 15px 0;
66}
67.alert {
68  background: rgba(231, 76, 60, 0.2);
69  border: 2px solid #e74c3c;
70  color: #e74c3c;
71  padding: 20px;
72  border-radius: 12px;
73  font-size: 16px;
74}
75</style>

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Który JavaScript hook jest wywoływany gdy element wchodzi do DOM?

  2. 2. Co należy wywołać na końcu hooka @enter aby poinformować Vue o zakończeniu animacji?

Zadania praktyczne w grze

  • Układanie w pionie

    Ułóż hooki JavaScript Transition w kolejności wywołania (wejście):

  • Edytor kodu

    Zaimplementuj @enter i @leave z użyciem el.style i done() callback.

  • Klikanie w kolejności

    Ułóż kod hooka @enter w prawidłowej kolejności:

  • Układanie w poziomie

    Ułóż składnię Transition wyłączającą klasy CSS:

  • Edytor kodu

    Użyj :css='false' i hooków JS do animacji opacity i scale.

  • Układanie w poziomie

    Ułóż deklarację hooka @leave w template:

Przydatne artykuły