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.
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');
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>
: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>
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>
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.
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>
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 programmatiqueuseRoute(): lecture des params et query stringsrouter.beforeEach(): protection des routes authentifiées- Imports dynamiques : lazy loading natif sans configuration supplémentaire