Introduction au Routage avec Vue-Router
Dans les applications web traditionnelles, la navigation entre les pages se fait généralement via des hyperliens. Cependant, les applications développées avec Vue sont des applications monopages (SPA) où le contenu change dynamiquement sans recharger la page complète. Pour simuler une navigation entre "pages" dans une SPA, nous utilisons un système de routage. Avec Vue-Router, le changement de "page" correspond en réalité à un changement de composant affiché. Le routage agit ainsi comme un gestionnaire de chemins pour les applications monopages.
Les applications Vue monopages sont basées sur le concept de routes et de composants. Les routes définissent les chemins d'accès et établissent une correspondance entre ces chemins et les composants à afficher.
- Mise en Rapide avec Vue-Router
1.1 Création d'un Projet
Commencez par créer un projet Vite :
npm create vite
Naviguez dans le répertoire du projet et installez les dépendances :
npm install
Installez ensuite le package vue-router :
npm install vue-router
1.2 Processus de Fonctionnement du Routage
Dans le dossier src/components, définissez plusieurs composants (par exemple, accueil.vue, produit.vue, service.vue). Dans le dossier src, créez un répertoire router (le nom peut varier) et ajoutez-y un fichier index.js contenant la configuration des routes :
// Importation des fonctions nécessaires de vue-router
import { createRouter, createWebHashHistory } from 'vue-router'
// Importation du composant d'accueil
import accueil from '../components/accueil.vue'
// Définition de la table des routes
const routes = [
// Chemin d'accès au composant et composant associé
{ path: '/accueil', component: accueil },
// Syntaxe raccourcie pour le chargement dynamique des composants
{ path: '/produit', component: () => import('../components/produit.vue') },
{ path: '/service', component: () => import('../components/service.vue') }
]
// Création de l'instance du routeur
const routeur = createRouter({
history: createWebHashHistory(),
routes: routes
})
// Exportation du routeur
export default routeur
Modifiez le fichier main.js pour enregistrer le routeur dans l'instance Vue :
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// Importation du routeur
import routeur from "./router/index.js";
// Création de l'application Vue
let app = createApp(App);
// Enregistrement du routeur
app.use(routeur)
// Montage de l'application
app.mount('#app')
Dans App.vue, configurez les liens de navigation et la vue du routeur :
<template>
<div>
<h1>Bienvenue dans notre Application</h1>
<!-- Configuration des liens de navigation -->
<router-link to="/accueil">Aller à l'accueil</router-link>
<br>
<router-link to="/produit">Aller aux produits</router-link>
<br>
<router-link to="/service">Aller aux services</router-link>
<hr>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view />
</div>
</template>
- Transmission de Paramètres avec useRoute
La transmission de paramètres dans les routes Vue est généralement utilisée lors de la navigation d'une route parente vers une route enfant, en passant des paramètres. Nous pouvons distinguer deux méthodes principales : la transmission par params et par query. La transmission par params peut elle-même se subdiviser en deux apporches : l'affichage ou non des paramètres dans l'URL.
2.1 Paramètres de Chemin - params
Les paramètres de chemin sont une méthode de transmission par params, similaire à l'annotation @PathVariable dans SpringMVC, où les paramètres sont intégrés dans une partie du chemin.
1) Transmission Simple
Définissons un composant article.vue :
<script setup>
// Import de l'objet useRoute
import { useRoute } from "vue-router";
// Récupération de l'objet route
let route = useRoute();
console.log('Objet route:', route);
</script>
<template>
<div>
<!-- Récupération des paramètres via l'objet global $route -->
<h3>Récupération des params via l'objet global $route :</h3>
<h4> {{ $route.params }} </h4>
<hr>
<!-- Récupération des paramètres via l'objet route -->
<h3>Récupération des params via l'objet route : </h3>
<h4> {{ route.params }} </h4>
</div>
</template>
Définissez la route correspondante :
{path: '/article/:id', component: () => import('../components/article.vue')}
Ajoutez les liens de navigation dans App.vue :
<template>
<div>
<h2>Bienvenue dans notre Application</h2>
<!-- Configuration des liens de navigation -->
<router-link to="/accueil">Aller à l'accueil</router-link>
<br>
<router-link to="/article/100">Aller à l'article 100</router-link>
<br>
<router-link to="/article/200">Aller à l'article 200</router-link>
<hr>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view />
</div>
</template>
2) Transmission de Plusieurs Paramètres
Pour transmettre plusieurs paramètres via le chemin, il suffit d'ajouter plusieurs paramètres dans le chemin défini.
Définissez la route :
{path: '/utilisateur/:id/:nom/:age', component: () => import('../components/utilisateur.vue')},
Ajoutez les liens de navigation dans App.vue :
<template>
<div>
<h2>Bienvenue dans notre Application</h2>
<!-- Configuration des liens de navigation -->
<router-link to="/accueil">Aller à l'accueil</router-link>
<br>
<router-link to="/utilisateur/100/Marie/28">Aller à l'utilisateur Marie</router-link>
<br>
<router-link to="/utilisateur/200/Jean/35">Aller à l'utilisateur Jean</router-link>
<hr>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view />
</div>
</template>
3) Transmission par Objet
La transmission par objet permet de passer des paramètres de format JSON dans les liens.
Définissez la route (avec un nom obligatoire pour la transmission par objet) :
// La transmission par objet nécessite obligatoirement une propriété name
{
name: "produit",
path: '/produit/:id/:nom/:prix/:description',
component: () => import('../components/produit.vue')
},
Ajoutez les liens de navigation dans App.vue :
<template>
<div>
<h2>Bienvenue dans notre Application</h2>
<!-- Configuration des liens de navigation -->
<router-link to="/accueil">Aller à l'accueil</router-link>
<br>
<router-link :to="{
name: 'produit',
params: {
id: 100,
nom: 'Smartphone X Pro',
prix: 899.00,
description: 'Écran OLED haute résolution'
}
}">Aller au produit</router-link>
<br>
<router-link :to="{
name: 'produit',
params: {
id: 200,
nom: 'Ordinateur Portable Ultra',
prix: 1299.00,
description: 'Processeur rapide, SSD 1TB'
}
}">Aller à l'ordinateur</router-link>
<hr>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view/>
</div>
</template>
2.2 Paramètres de Recherche - query
La méthode de transmission par query ajoute les paramètres à l'URL après un point d'interrogation, similaire à la saisie directe de paramètres dans la barre d'adresse du navigateur.
1) Transmission Simple
Définissez un composant departement.vue :
<script setup>
// Import de l'objet useRoute
import { useRoute } from "vue-router";
// Récupération de l'objet route
let route = useRoute();
</script>
<template>
<div>
<!-- Récupération des paramètres via l'objet global $route -->
<h3>Récupération des query via l'objet global $route :</h3>
<!-- Note: on accède aux paramètres via l'objet query, et non params -->
<h4> {{ $route.query }} </h4>
<hr>
<!-- Récupération des paramètres via l'objet route -->
<h3>Récupération des query via l'objet route : </h3>
<!-- Note: on accède aux paramètres via l'objet query, et non params -->
<h4> {{ route.query }} </h4>
</div>
</template>
Définissez la route correspondante :
{name: 'departement', path: '/departement', component: () => import('../components/departement.vue')},
Ajoutez les liens de navigation dans App.vue :
<template>
<div>
<h2>Bienvenue dans notre Application</h2>
<!-- Configuration des liens de navigation -->
<router-link to="/accueil">Aller à l'accueil</router-link>
<br>
<router-link to="/departement?id=100&nom=Marketing">Aller au département Marketing</router-link>
<br>
<router-link to="/departement?id=200&nom=RH">Aller au département RH</router-link>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view/>
</div>
</template>
2) Transmission par Objet
La transmission par query supporte également la transmission d'objets paramétrés.
Ajoutez les liens de navigation dans App.vue :
<template>
<div>
<h2>Bienvenue dans notre Application</h2>
<router-link to="/accueil">Aller à l'accueil</router-link>
<br>
<router-link :to="{
// On peut utiliser name ou path pour transmettre des paramètres
name: 'departement',
query: {
id: 100,
nom: 'Marketing'
}
}">Aller au département Marketing</router-link>
<br>
<router-link :to="{
// On peut utiliser name ou path pour transmettre des paramètres
// name: 'departement',
path: '/departement',
query: {
id: 200,
nom: 'RH'
}
}">Aller au département RH</router-link>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view/>
</div>
</template>
- Routes Imbriquées
Certaines applications ont des interfaces utilisateur composées de plusieurs couches de composants imbriqués. Dans ce cas, les segments d'URL correspondent généralement à une structure de composants imbriqués spécifique.
Exemple de structure de routes imbriquées :
/profil-utilisateur /Articles-utilisateur
┌──────────────────┐ ┌──────────────────┐
│ Utilisateur │ │ Utilisateur │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Profil │ │ ●────────────▶ │ │ Articles │ │
│ │ │ │ │ │ │ │
│ └──────────────┘ │ │ └──────────────┘ │
└──────────────────┘ └──────────────────┘
Dans les routes imbriquées, une route principale contient des routes enfants. Par exemple, une route utilisateur pourrait avoir des routes enfants comme profil et articles.
Configurez App.vue :
<template>
<div>
<h2>Bienvenue dans notre Application</h2>
<!-- Configuration des liens de navigation -->
<router-link to="/">Aller à l'accueil</router-link>
<br>
<router-link to="/utilisateur">Aller à l'espace utilisateur</router-link>
<hr>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view />
</div>
</template>
Créez un composant utilisateur.vue :
<template>
<div>
<h3>Ceci est l'espace utilisateur</h3>
<router-link to="/utilisateur/profil">Mon profil</router-link>
<br>
<router-link to="/utilisateur/articles">Mes articles</router-link>
<hr>
<router-view></router-view>
</div>
</template>
Définissez la table des routes avec des routes enfants :
// Définition de la table des routes
const routes = [
...
{
path: '/utilisateur', component: () => import('../views/utilisateur.vue'),
children: [
// Les chemins ici doivent être relatifs
{path: 'profil', component: () => import('../views/utilisateur/profil.vue')},
{path: 'articles', component: () => import('../views/utilisateur/articles.vue')}
]
}
...
]
- Navigation Programmée avec useRouter
Le rôle du routage client dans les applications monopages (SPA) est de lier l'URL du navigateur au contenu affiché à l'utilisateur. Lorsque l'utilisateur navigue entre différentes pages de l'aplication, l'URL se met à jour, mais la page entière n'a pas besoin d'être rechargée depuis le serveur.
Vue Router est construit sur le système de composants de Vue. Nous pouvons configurer les routes pour indiquer à Vue Router quels composants afficher pour chaque chemin d'URL.
De plus, nous pouvons utiliser l'objet useRouter de vue-router pour effcetuer une navigation programmée, c'est-à-dire effectuer des changements de route via du code.
Voici un exemple de table de routes :
// Définition de la table des routes
const routes = [
{path: '/accueil', component: accueil},
{name: 'departement', path: '/departement',
component: () => import('../components/departement.vue')
},
{path: '/utilisateur/:id/:nom/:age',
component: () => import('../components/utilisateur.vue')
},
// La transmission par objet nécessite obligatoirement une propriété name
{name: "produit", path: '/produit/:id/:nom/:prix/:description',
component: () => import('../components/produit.vue')
},
{path: '/article/:id',
component: () => import('../components/article.vue')
}
]
Configurez App.vue avec des boutons pour la navigation programmée :
<template>
<div>
<h2>Bienvenue dans notre Application</h2>
<router-link to="/accueil">Aller à l'accueil</router-link>
<br>
<button @click="versArticle">Navigation par chemin - paramètre unique</button>
<button @click="versUtilisateur">Navigation par chemin - plusieurs paramètres</button>
<button @click="versProduit">Navigation par objet - paramètres</button>
<button @click="versDepartement_01">Navigation par query - paramètres simples</button>
<button @click="versDepartement_02">Navigation par query - paramètres objet</button>
<!-- Espace réservé pour l'affichage des composants de route -->
<router-view/>
</div>
</template>
<script setup>
// Import de useRouter
import { useRouter } from 'vue-router'
// Création de l'instance du routeur
let routeur = useRouter();
function versArticle(){
routeur.push("/article/100");
}
function versUtilisateur(){
routeur.push("/utilisateur/100/Marie/28");
}
function versProduit(){
routeur.push({
name: 'produit',
params: {
id: 100,
nom: 'Smartphone X Pro',
prix: 899.00,
description: 'Écran OLED haute résolution'
}
});
}
function versDepartement_01(){
routeur.push("/departement?id=100&nom=Marketing");
}
function versDepartement_02(){
routeur.push({
name: 'departement',
query: {
id: 200,
nom: 'RH'
}
});
}
</script>
L'utilisation de Router permet également d'effectuer une navigation en arrière. Par exemple, ajoutez le code suivant dans un composant enfant :
<script setup>
// Import de l'objet useRouter
import { useRouter } from "vue-router";
// Récupération de l'objet routeur
let routeur = useRouter();
function retour() {
// go représente l'avance, back représente le retour
// go(-1) revient en arrière d'une page
routeur.go(-1);
// routeur.back(); fait la même chose
}
</script>
<template>
<div>
<h3>Page article</h3>
<button @click="retour">Retour</button>
</div>
</template>
- Gardes de Navigation dans Vue-Router
Les gardes de navigation permettent d'exécuter des fonctions personnalisées avant, pendant ou après une navigation, similaire aux fonctionnalités d'un intercepteur. Elles sont principalement utilisées pour le contrôle d'accès, le préchargement de données, la limitation d'accès à certaines pages, etc.
Les fonctions de garde de navigation généralement acceptent trois paramètres :
- to : l'objet de route vers lequel on navigue ;
- from : l'objet de route depuis lequel on navigue ;
- next : une fonction à appeler pour continuer la navigation. Si elle n'est pas appelée, la navigation est interrompue.
next('/login'); # Redirection vers /login
next({name:'login'}); # Redirection vers le composant login
next({path:'/login'}); # Redirection vers /login
next(); # Poursuite de la navigation
next(false); # Interruption de la navigation
next('/'); # Redirection vers une nouvelle adresse
5.1 Gardes Globales
Les gardes globales sont des fonctions directement associées à l'instance du routeur. Elles sont déclenchées pour toutes les routes configurées.
- beforeEach (to, from, next) : déclenchée avant la navigation, principalement utilisée pour la vérification de connexion.
- beforeResolve (to, from, next) : similaire à beforeEach, mais déclenchée après la résolution des composants.
- afterEach (to, from) : déclenchée après la navigation, sans fonction next.
Définissez des gardes globales dans index.js :
// Définition d'une garde globale de pré-navigation
routeur.beforeEach((to, from, next) => {
console.log("Garde to :", to)
console.log("Garde from :", from)
// Si l'accès est à /departement, vérifions si l'utilisateur est connecté
if(to.path === '/departement'){
let estConnecte = false; // Simulons que l'utilisateur n'est pas connecté
if(estConnecte){
next(); // Continuer la navigation (autoriser l'accès à /departement)
}else{
routeur.push('/connexion'); // Redirection vers la page de connexion
}
}
// Pour les autres routes, continuer la navigation
next();
})
5.2 Gardes de Route
Les gardes de route peuvent être définies directement dans la configuration d'une route spécifique.
- beforeEnter (to, from, next) : similaire à beforeEach, mais spécifique à une route.
Par exemple, ajoutons une garde de route à la route accueil :
{
path: '/accueil', component: accueil, beforeEnter: (to, from, next) => {
console.log("Garde beforeEnter to :", to)
console.log("Garde beforeEnter from :", from)
next();
}
}
5.3 Gardes de Composant
Les gardes de composant sont des fonctions définies à l'intérieur des composants, similaires aux cycles de vie des composants.
- beforeRouteEnter (to, from, next) : avant l'entrée dans le composant.
- beforeRouteUpdate (to, from, next) : lorsque la route change mais que le composant est réutilisé.
- beforeRouteLeave (to, from, next) : avant de quitter le composant.
Par exemple, ajoutons des gardes de composant dans accueil.vue :
<script setup>
function beforeRouteEnter(to, from, next) {
console.log("Garde beforeRouteEnter to :", to)
console.log("Garde beforeRouteEnter from :", from)
next();
}
</script>
<template>
<div>
<h3>Ceci est la page d'accueil</h3>
</div>
</template>