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

Transition między routami

3 min czytania
W tej lekcji5

W NOVA LAB przechodzenie między sekcjami stacji - z centrum dowodzenia do laboratorium, z reaktora do hangaru - powinno być płynne i naturalne. Vue Router wspiera animacje przejść między stronami dzięki integracji z komponentem <Transition>.

RouterView + Transition

Aby animować zmianę widoku routera, używasz slot API na <RouterView>. Vue Router udostępnia aktualny komponent jako zmienną slotową:

1<RouterView v-slot="{ Component }">
2  <Transition name="page" mode="out-in">
3    <component :is="Component" />
4  </Transition>
5</RouterView>

Jak to działa krok po kroku:

  1. <RouterView v-slot="{ Component }"> - router dostarcza aktualny komponent strony jako Component
  2. <Transition name="page" mode="out-in"> - opakowujesz dynamiczny komponent w Transition
  3. <component :is="Component" /> - renderujesz dynamiczny komponent strony

Trzy kluczowe zasady:

  • Użyj v-slot="{ Component }" - nie możesz bezpośrednio owinąć <RouterView> w <Transition> (to nie zadziała w Vue 3)
  • Zawsze dodaj mode="out-in" - bez tego stara i nowa strona będą animowane jednocześnie, co wygląda chaotycznie
  • Nie dodawaj :key na <component> - Vue Router automatycznie reaguje na zmianę routy

Odpowiednie klasy CSS:

1.page-enter-active,
2.page-leave-active {
3  transition: all 0.3s ease;
4}
5
6.page-enter-from {
7  opacity: 0;
8  transform: translateX(20px);
9}
10
11.page-leave-to {
12  opacity: 0;
13  transform: translateX(-20px);
14}

Per-route transitions

Każda sekcja stacji NOVA LAB może mieć inny typ animacji - centrum dowodzenia wsuwa się z lewej, panel alertów wyskakuje z dołu. Użyj pola meta w definicji routy, aby przypisać nazwę animacji:

1const routes = [
2  {
3    path: '/dashboard',
4    component: Dashboard,
5    meta: { transition: 'slide-left' }
6  },
7  {
8    path: '/settings',
9    component: Settings,
10    meta: { transition: 'slide-right' }
11  },
12  {
13    path: '/alerts',
14    component: Alerts,
15    meta: { transition: 'slide-up' }
16  }
17]

W template odczytaj nazwę animacji z obiektu route:

1<RouterView v-slot="{ Component, route }">
2  <Transition :name="route.meta.transition || 'fade'" mode="out-in">
3    <component :is="Component" />
4  </Transition>
5</RouterView>

Zwróć uwagę na || 'fade' - to fallback dla routów bez zdefiniowanej animacji. Slot v-slot daje dostęp zarówno do Component (aktualny komponent strony) jak i route (obiekt routy z meta danymi).

Dynamiczne animacje na podstawie kierunku nawigacji

Możesz zmieniać animację w zależności od tego, czy użytkownik nawiguje "w przód" czy "w tył":

1<script setup>
2import { ref } from 'vue'
3import { useRouter } from 'vue-router'
4
5const transitionName = ref('slide-left')
6const router = useRouter()
7
8router.beforeEach((to, from) => {
9  // Porównaj indeksy stron aby określić kierunek
10  const toDepth = to.path.split('/').length
11  const fromDepth = from.path.split('/').length
12
13  transitionName.value = toDepth < fromDepth ? 'slide-right' : 'slide-left'
14})
15</script>
16
17<template>
18  <RouterView v-slot="{ Component }">
19    <Transition :name="transitionName" mode="out-in">
20      <component :is="Component" />
21    </Transition>
22  </RouterView>
23</template>

Z KeepAlive

Możesz łączyć Transition z KeepAlive, aby cache'ować widoki stron. To przydatne gdy użytkownik często przechodzi między tymi samymi sekcjami stacji i nie chcesz tracić stanu (np. pozycji scrolla, wprowadzonych danych):

1<RouterView v-slot="{ Component }">
2  <Transition name="fade" mode="out-in">
3    <KeepAlive :max="5">
4      <component :is="Component" />
5    </KeepAlive>
6  </Transition>
7</RouterView>

Kolejność jest istotna - <Transition> na zewnątrz, <KeepAlive> wewnątrz. Atrybut :max="5" ogranicza liczbę cache'owanych komponentów, aby nie zużywać nadmiernej ilości pamięci.

Uwagi praktyczne

  • Animacje przejść między stronami powinny być krótkie (200-400ms) - użytkownik chce szybko zobaczyć treść
  • Unikaj ciężkich animacji (np. 3D transforms) na urządzeniach mobilnych
  • Testuj animacje na wolniejszych urządzeniach - efekt, który wygląda świetnie na szybkim komputerze, może lagować na tablecie
  • Preferuj opacity i transform - te właściwości są akcelerowane przez GPU
Kod do tej lekcji: App.vue
1<script setup>
2import { ref } from 'vue'
3
4// Symulacja routera z komponentami
5const currentRoute = ref('home')
6const routes = {
7  home: { name: 'Panel główny', icon: '' },
8  sensors: { name: 'Czujniki', icon: '' },
9  crew: { name: 'Załoga', icon: '' }
10}
11</script>
12
13<template>
14  <div class="nova-lab">
15    <h1>Transition między routami</h1>
16    <p style="color: #888;">Symulacja Transition z RouterView</p>
17
18    <nav class="nav">
19      <button
20        v-for="(route, key) in routes"
21        :key="key"
22        @click="currentRoute = key"
23        :class="{ active: currentRoute === key }"
24        class="nav-link"
25      >
26        {{ route.icon }} {{ route.name }}
27      </button>
28    </nav>
29
30    <!-- Symulacja: RouterView v-slot + Transition -->
31    <Transition name="page" mode="out-in">
32      <div :key="currentRoute" class="page">
33        <h2>{{ routes[currentRoute].icon }} {{ routes[currentRoute].name }}</h2>
34        <p>Zawartość strony: {{ currentRoute }}</p>
35      </div>
36    </Transition>
37  </div>
38</template>
39
40<style scoped>
41.nova-lab {
42  background: #0a0e27;
43  color: #00ff88;
44  min-height: 100vh;
45  padding: 20px;
46  font-family: monospace;
47}
48h1 { color: #00ff88; }
49.nav {
50  display: flex;
51  gap: 8px;
52  margin: 15px 0;
53  border-bottom: 2px solid #1a1e3a;
54  padding-bottom: 10px;
55}
56.nav-link {
57  background: transparent;
58  color: #00b4d8;
59  border: 1px solid transparent;
60  padding: 8px 16px;
61  border-radius: 6px 6px 0 0;
62  cursor: pointer;
63}
64.nav-link.active {
65  background: rgba(0, 180, 216, 0.15);
66  border-color: #00b4d8;
67  border-bottom-color: transparent;
68}
69.page {
70  background: rgba(0, 255, 136, 0.05);
71  border: 2px solid #00ff88;
72  padding: 30px;
73  border-radius: 0 12px 12px 12px;
74  min-height: 150px;
75}
76
77/* Przejście strony */
78.page-enter-active,
79.page-leave-active {
80  transition: all 0.3s ease;
81}
82.page-enter-from {
83  opacity: 0;
84  transform: translateY(20px);
85}
86.page-leave-to {
87  opacity: 0;
88  transform: translateY(-20px);
89}
90</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. Jak dodać animację przejścia między stronami w Vue Router?

  2. 2. Jak zdefiniować nazwę animacji per-route w Vue Router?

Zadania praktyczne w grze

  • Układanie w pionie

    Ułóż zagnieżdżenie komponentów dla animacji routingu:

  • Edytor kodu

    Owiń RouterView v-slot w <Transition> z mode='out-in'.

  • Układanie w poziomie

    Ułóż składnię RouterView z v-slot:

  • Klikanie w kolejności

    Ułóż kod dynamicznej nazwy transition per-route:

Przydatne artykuły