Vue Router est la solution officielle de routage pour les applications monopages (SPA) en Vue 3 : elle change l'URL sans rechargement complet, affiche le bon composant et fonctionne correctement avec les boutons précédent et suivant du navigateur. Ce guide couvre la définition des routes, les paramètres dynamiques, la navigation programmatique et les navigation guards qui pilotent le contrôle d'accès, avec des exemples réels. Tout ici vise Vue Router 4 (la version utilisée avec Vue 3).
Installation et définition de route de base
Installez le paquet et créez une instance de router. createRouter reçoit un mode history et un tableau routes :
npm install vue-router@4
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{ path: '/', name: 'home', component: Home },
{ path: '/about', name: 'about', component: About },
]
export const router = createRouter({
history: createWebHistory(),
routes,
})
Branchez ensuite le router dans l'application :
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router'
createApp(App).use(router).mount('#app')
<router-view> décide où le composant correspondant est rendu, et vous créez les liens avec <router-link> afin d'éviter tout rechargement de page :
<router-link to="/">Accueil</router-link>
<router-link :to="{ name: 'about' }">À propos</router-link>
<router-view />
Donner un nom aux routes est une bonne habitude : même si la structure des URL change, les liens construits avec name continuent de fonctionner.
Mode history : web history ou hash ?
Il existe deux choix courants. createWebHistory() produit des URL propres (/about) mais exige que votre serveur redirige tout chemin inconnu vers index.html ; sinon vous obtenez une 404 au rechargement. createWebHashHistory() ajoute un # à l'URL (/#/about) et ne nécessite aucune configuration serveur — pratique pour l'hébergement statique, mais moins esthétique et moins bon pour le SEO. La plupart des projets modernes préfèrent le web history en ajoutant une règle de fallback sur le serveur.
Paramètres dynamiques
Les segments d'un chemin commençant par : sont des paramètres dynamiques. Par exemple une page de détail :
const routes = [
{ path: '/users/:id', name: 'user', component: UserDetail },
]
Dans le composant, vous lisez le paramètre avec useRoute(). Une utilisation typique avec la Composition API ressemble à ceci :
<script setup>
import { useRoute } from 'vue-router'
import { watch, ref } from 'vue'
const route = useRoute()
const user = ref(null)
async function load(id) {
user.value = await fetch(`/api/users/${id}`).then(r => r.json())
}
load(route.params.id)
// Surveiller les changements de paramètre quand le composant est réutilisé
watch(() => route.params.id, (id) => load(id))
</script>
Il y a un point critique ici : lorsque l'utilisateur passe de /users/1 à /users/2, Vue réutilise la même instance du composant, qui n'est donc pas recréé. C'est pourquoi vous devez watch route.params.id pour recharger les données. Si vous préférez recevoir le paramètre comme prop, définissez props: true sur la route ; votre composant reçoit alors id comme simple prop et devient plus facile à tester.
Utilisez :id? pour un paramètre optionnel, et le motif /:pathMatch(.*)* pour capturer plusieurs segments ; ce dernier sert généralement à la page 404.
Navigation programmatique et paramètres de requête
Pour naviguer depuis le code après l'envoi d'un formulaire ou la fin d'une action, utilisez useRouter() :
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
function goToUser(id) {
router.push({ name: 'user', params: { id } })
}
function search(term) {
router.push({ path: '/search', query: { q: term } })
}
</script>
Les paramètres de requête (?q=...) se lisent via route.query. Utilisez router.replace() pour modifier l'étape courante sans ajouter d'entrée dans l'historique, et router.back() pour revenir en arrière.
Navigation guards : contrôle d'accès
Les guards permettent d'intervenir avant qu'une transition n'ait lieu pour l'autoriser, la rediriger ou l'annuler — l'outil central pour l'authentification. Le guard global le plus courant est beforeEach :
router.beforeEach((to, from) => {
const isAuth = !!localStorage.getItem('token')
if (to.meta.requiresAuth && !isAuth) {
// Retourner un objet location redirige la transition vers cet endroit
return { name: 'login', query: { redirect: to.fullPath } }
}
// Retourner true ou rien autorise la transition
})
Le style moderne dans Vue Router 4 consiste à retourner une valeur plutôt qu'appeler next() : false annule la transition, un objet location redirige, et tout le reste (ou undefined) l'autorise. Vous marquez les routes protégées avec le champ meta de la définition de route :
{
path: '/dashboard',
name: 'dashboard',
component: Dashboard,
meta: { requiresAuth: true },
}
Si vous ne devez protéger qu'une seule route, utilisez le guard beforeEnter propre à cette route. Dans un composant, onBeforeRouteLeave permet d'exécuter des contrôles du type « vous avez des modifications non enregistrées, voulez-vous vraiment quitter ? »
Lazy loading et routes imbriquées
Dans les grandes applications, charger toutes les vues d'emblée ralentit l'ouverture initiale. En passant le composant sous forme d'import() dynamique, vous obtenez un découpage du code par route ; ce chunk n'est téléchargé qu'au moment où la route est visitée :
const routes = [
{ path: '/about', component: () => import('../views/About.vue') },
]
Pour des mises en page imbriquées (par exemple des onglets sur un profil utilisateur), utilisez children et placez un second <router-view> dans le template du composant parent :
{
path: '/users/:id',
component: UserLayout,
children: [
{ path: '', component: UserOverview },
{ path: 'posts', component: UserPosts },
],
}
Questions fréquentes
Pourquoi ma page ne se met-elle pas à jour quand le paramètre change ?
Parce que Vue Router réutilise le même composant au lieu de le recréer. Soit vous faites un watch sur route.params pour recharger les données, soit vous donnez au composant une :key unique pour forcer un remontage.
Pourquoi obtenir une 404 en rechargeant la page ?
En mode web history, votre serveur ne connaît pas les chemins comme /about. Configurez le serveur pour rediriger toutes les requêtes non correspondantes vers index.html (le fallback SPA) ; si c'est impossible, utilisez le hash history.
Dois-je utiliser next() ou return dans beforeEach ?
Dans Vue Router 4, retourner une valeur est recommandé ; c'est plus propre et moins sujet aux erreurs. next() fonctionne toujours, mais ne mélangez pas les deux dans le même guard, sinon la transition risque d'être traitée deux fois.
Le routage de votre projet Vue est-il devenu désordonné ? Revoyons ensemble la structure de vos routes, vos guards et le découpage du code pour en faire une architecture solide. Contactez-moi et nous construirons une solution adaptée à vos besoins.