Cours Vue.js · Module 13: Transitions et animations

Transition entre les routes

4 min de lecture
Dans cette leçon5

Au NOVA LAB, passer d'une section de la station à une autre - du centre de commande au laboratoire, du réacteur au hangar - doit être fluide et naturel. Vue Router prend en charge les animations de transition entre les pages grâce à son intégration avec le composant <Transition>.

RouterView + Transition

Pour animer les changements de vue du routeur, tu utilises l'API de slot sur <RouterView>. Vue Router fournit le composant courant comme variable de slot :

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

Voici comment cela fonctionne étape par étape :

  1. <RouterView v-slot="{ Component }"> - le routeur fournit le composant de page courant sous le nom Component
  2. <Transition name="page" mode="out-in"> - tu enveloppes le composant dynamique dans une Transition
  3. <component :is="Component" /> - tu rends le composant de page dynamique

Trois règles clés :

  • Utilise v-slot="{ Component }" - tu ne peux pas envelopper directement <RouterView> dans <Transition> (cela ne fonctionne pas en Vue 3)
  • Ajoute toujours mode="out-in" - sans lui, l'ancienne et la nouvelle page s'animeront simultanément, ce qui paraît chaotique
  • N'ajoute pas de :key sur <component> - Vue Router réagit automatiquement aux changements de route

Les classes CSS correspondantes :

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}

Transitions par route

Chaque section de la station NOVA LAB peut avoir un type d'animation différent - le centre de commande glisse depuis la gauche, le panneau d'alertes surgit depuis le bas. Utilise le champ meta dans la définition de la route pour attribuer un nom d'animation :

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]

Dans le template, lis le nom de l'animation depuis l'objet 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>

Remarque le || 'fade' - c'est une valeur de repli pour les routes sans animation définie. Le v-slot te donne accès à la fois à Component (le composant de page courant) et à route (l'objet route avec ses métadonnées).

Animations dynamiques basées sur le sens de navigation

Tu peux changer l'animation selon que l'utilisateur navigue « en avant » ou « en arrière » :

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  // Compare la profondeur des pages pour déterminer le sens
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>

Avec KeepAlive

Tu peux combiner Transition avec KeepAlive pour mettre en cache les vues de page. C'est utile quand l'utilisateur bascule fréquemment entre les mêmes sections de la station et que tu ne veux pas perdre l'état (par exemple la position de défilement, les données saisies) :

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>

L'ordre compte - <Transition> à l'extérieur, <KeepAlive> à l'intérieur. L'attribut :max="5" limite le nombre de composants mis en cache pour éviter une consommation excessive de mémoire.

Notes pratiques

  • Les animations de transition entre pages doivent être courtes (200-400 ms) - l'utilisateur veut voir le contenu rapidement
  • Évite les animations lourdes (par exemple les transforms 3D) sur les appareils mobiles
  • Teste les animations sur des appareils plus lents - un effet qui rend bien sur un ordinateur rapide peut ramer sur une tablette
  • Privilégie opacity et transform - ces propriétés sont accélérées par le GPU
Code de cette leçon : App.vue
1<script setup>
2import { ref } from 'vue'
3
4// Simulation de routeur avec des composants
5const currentRoute = ref('home')
6const routes = {
7  home: { name: 'Tableau de bord', icon: '' },
8  sensors: { name: 'Capteurs', icon: '' },
9  crew: { name: 'Équipage', icon: '' }
10}
11</script>
12
13<template>
14  <div class="nova-lab">
15    <h1>Transitions de route</h1>
16    <p style="color: #888;">Simulation de Transition avec 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    <!-- Simulation : 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>Contenu de la page : {{ 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/* Transition de page */
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>

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Comment ajoute-t-on une animation de transition entre les pages dans Vue Router ?

  2. 2. Comment définit-on un nom d'animation par route dans Vue Router ?

Tâches pratiques dans le jeu

  • Tri vertical

    Range l'imbrication des composants pour l'animation de routage :

  • Éditeur de code

    Enveloppe RouterView v-slot dans <Transition> avec mode='out-in'.

  • Tri horizontal

    Range la syntaxe de RouterView avec v-slot :

  • Clique dans l'ordre

    Range le code pour un nom de transition dynamique par route :