Routing Vue.js : guide complet Vue Router 4

🏷️ Front-end 📅 15/04/2026 12:00:00 👤 Mezgani said
Vue Vue Router Routing Javascript Spa Lazy Loading
Routing Vue.js : guide complet Vue Router 4

Apprenez à configurer et utiliser Vue Router 4 dans vos applications Vue.js : routes dynamiques, navigation programmatique, guards et lazy loading.

Pourquoi Vue Router 4 ?

Vue Router est la solution officielle de routage pour Vue.js. La version 4, compatible avec Vue 3 et la Composition API, apporte une intégration profonde avec les composables, un meilleur support TypeScript et une API cohérente avec l'écosystème Vue 3.

Vue Router v4 gère côté client la correspondance URL ↔ composant, permettant de construire des SPA (Single Page Applications) avec une navigation fluide, sans rechargement de page.

À retenir : Vue Router 4 est la version officielle pour Vue 3. Si votre projet utilise Vue 2, vous devez rester sur Vue Router 3.

Installation et configuration

Installez Vue Router dans votre projet Vue 3 :

# npm
npm install vue-router@4

# yarn
yarn add vue-router@4

Créez ensuite votre fichier de routeur (conventionnellement src/router/index.ts) :

// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import Home    from '@/views/Home.vue';
import About   from '@/views/About.vue';

const routes = [
  { path: '/',       component: Home },
  { path: '/about',  component: About },
  // Catch-all pour le 404
  { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('@/views/NotFound.vue') }
];

const router = createRouter({
  // createWebHistory = URLs propres sans #
  history: createWebHistory(import.meta.env.BASE_URL),
  routes
});

export default router;

Déclarez ensuite le routeur dans votre application Vue :

// main.ts
import { createApp } from 'vue';
import App    from './App.vue';
import router from './router';

createApp(App).use(router).mount('#app');
Note : createWebHistory utilise l'API History HTML5 (URLs propres). createWebHashHistory utilise le # dans l'URL si votre serveur ne supporte pas les redirections vers index.html.

Définir vos routes

Chaque route est un objet avec au minimum un path et un component. Il est recommandé d'ajouter un name pour faciliter la navigation programmatique :

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/articles',
    name: 'articles',
    component: ArticleList,
    // Meta personnalisées (ex : protection de route)
    meta: { requiresAuth: false }
  },
  {
    path: '/articles/:id',
    name: 'article-detail',
    component: ArticleDetail,
    meta: { requiresAuth: true }
  }
];

Dans votre template, utilisez <RouterLink> pour la navigation interne et <RouterView /> pour afficher le composant de la route courante :

<!-- App.vue -->
<template>
  <nav>
    <RouterLink to="/">Accueil</RouterLink>
    <RouterLink :to="{ name: 'articles' }">Articles</RouterLink>
  </nav>

  <!-- Composant de la route active rendu ici -->
  <RouterView />
</template>
Bonne pratique : Préférez toujours :to="{ name: 'xxx' }" à to="/xxx" — si le chemin change, vous n'aurez à le modifier qu'à un seul endroit.

Routes imbriquées et RouterView

Les routes imbriquées permettent d'avoir un layout partagé avec un contenu variable. Le composant parent contient un <RouterView /> secondaire où les composants enfants sont rendus :

// src/router/index.ts
const routes = [
  {
    path: '/dashboard',
    component: DashboardLayout, // Layout avec sidebar
    children: [
      // Route index : affichée sur /dashboard exactement
      { path: '', name: 'dashboard',          component: DashboardHome },
      { path: 'stats',    name: 'stats',      component: Stats },
      { path: 'settings', name: 'settings',   component: Settings }
    ]
  }
];
<!-- views/DashboardLayout.vue -->
<template>
  <div class="dashboard">
    <aside>
      <RouterLink :to="{ name: 'dashboard' }">Vue d'ensemble</RouterLink>
      <RouterLink :to="{ name: 'stats' }">Statistiques</RouterLink>
      <RouterLink :to="{ name: 'settings' }">Paramètres</RouterLink>
    </aside>
    <main>
      <!-- Composant enfant actif rendu ici -->
      <RouterView />
    </main>
  </div>
</template>

Navigation programmatique

Avec la Composition API, utilisez le composable useRouter() pour naviguer par code :

<script setup lang="ts">
import { useRouter } from 'vue-router';

const router = useRouter();

async function handleLogin() {
  const success = await login(/* credentials */);

  if (success) {
    // Navigation vers une route nommée
    router.push({ name: 'dashboard' });
  }
}
</script>

Les méthodes disponibles sur l'instance router :

// Naviguer vers un chemin ou une route nommée
router.push('/about');
router.push({ name: 'articles', params: { id: 42 } });

// Passer des données d'état (non visibles dans l'URL)
router.push({ name: 'dashboard', state: { fromLogin: true } });

// Remplacer l'entrée courante (sans historique)
router.replace({ name: 'home' });

// Retour / avancer dans l'historique
router.go(-1); // équivalent de window.history.back()
router.go(1);  // équivalent de window.history.forward()
À retenir : router.replace() est idéal après une déconnexion pour éviter que l'utilisateur revienne à une page protégée avec le bouton "précédent".

Paramètres de route et query strings

Lisez les paramètres dynamiques et les query strings avec le composable useRoute() :

<script setup lang="ts">
import { useRoute } from 'vue-router';
import { computed } from 'vue';

const route = useRoute();

// Paramètre dynamique :id depuis path="/articles/:id"
const articleId = computed(() => route.params.id as string);

// Query string depuis ?page=2&sort=date
const currentPage = computed(() => Number(route.query.page) || 1);
const sortOrder   = computed(() => route.query.sort as string || 'date');
</script>

Pour passer des paramètres via RouterLink :

<!-- Paramètre dynamique -->
<RouterLink :to="{ name: 'article-detail', params: { id: article.id } }">
  {{ article.title }}
</RouterLink>

<!-- Query string -->
<RouterLink :to="{ name: 'articles', query: { page: 2, sort: 'date' } }">
  Page suivante
</RouterLink>
Conseil : Activez props: true dans la définition de la route pour recevoir les params directement en tant que props de composant — le composant devient plus réutilisable et testable.

Navigation Guards

Les navigation guards interceptent les changements de route. Le guard global beforeEach est la solution recommandée pour protéger des routes authentifiées :

// src/router/index.ts
import { useAuthStore } from '@/stores/auth';

router.beforeEach((to, from) => {
  const auth = useAuthStore();

  // Si la route nécessite une auth ET l'utilisateur n'est pas connecté
  if (to.meta.requiresAuth && !auth.isAuthenticated) {
    // Redirection vers login en conservant la destination
    return { name: 'login', query: { redirect: to.fullPath } };
  }
});

Les guards peuvent aussi être définis au niveau d'une route spécifique :

const routes = [
  {
    path: '/admin',
    component: AdminPanel,
    beforeEnter: (to, from) => {
      const auth = useAuthStore();
      if (!auth.isAdmin) return { name: 'forbidden' };
    }
  }
];
À retenir : Un guard retourne false pour annuler la navigation, un objet { name: '...' } pour rediriger, ou rien (/undefined) pour valider la navigation.

Lazy loading des routes

Le lazy loading charge les composants à la demande, réduisant la taille du bundle initial. En Vue Router 4, utilisez simplement les imports dynamiques dans la définition des routes :

// src/router/index.ts
const routes = [
  {
    path: '/',
    // Chargé immédiatement (page critique)
    component: Home
  },
  {
    path: '/dashboard',
    // Chargé uniquement quand l'utilisateur navigue vers /dashboard
    component: () => import('@/views/Dashboard.vue')
  },
  {
    path: '/settings',
    // Vite regroupe ces chunks dans le même fichier grâce au commentaire magique
    component: () => import(/* webpackChunkName: "settings" */ '@/views/Settings.vue')
  }
];

Ajoutez un composant de chargement global avec <Suspense> ou le slot #default de <RouterView> :

<!-- App.vue -->
<template>
  <RouterView v-slot="{ Component }">
    <Suspense>
      <!-- Le composant lazy chargé -->
      <component :is="Component" />

      <!-- Affiché pendant le chargement -->
      <template #fallback>
        <div class="loading">Chargement...</div>
      </template>
    </Suspense>
  </RouterView>
</template>
Conseil : Avec Vite, chaque import dynamique génère automatiquement un chunk séparé. La page d'accueil sera toujours rapide, et les autres pages ne seront chargées que si l'utilisateur y navigue.

Conclusion

Vue Router 4 s'intègre parfaitement à l'écosystème Vue 3 et à la Composition API. Les points clés à maîtriser :

  • createRouter + createWebHistory : configuration du routeur
  • <RouterLink> + <RouterView /> : navigation et rendu dans le template
  • Routes imbriquées avec children + <RouterView /> dans le layout
  • useRouter() : navigation programmatique
  • useRoute() : lecture des params et query strings
  • router.beforeEach() : protection des routes authentifiées
  • Imports dynamiques : lazy loading natif sans configuration supplémentaire
Prochaine étape : Combinez Vue Router avec Pinia (le store officiel Vue 3) pour gérer l'état d'authentification et des données partagées entre routes.