## Comment bien implémenter le bouton « Retour » dans Vue : Un guide technique pour les développeurs
L'implémentation du bouton « Retour » dans les applications Vue.js semble souvent simple, mais en pratique, elle entraîne de graves problèmes de navigation et d'historique du navigateur. Beaucoup de développeurs commettent l'erreur d'utiliser router.push() au lieu des méthodes conçues pour se déplacer dans la pile d'historique existante. Cela crée des entrées dupliquées, casse le comportement du bouton Retour du navigateur et provoque des boucles de transition infinies. Cet article fournit un guide techniquement précis pour implémenter correctement le bouton « Retour », en tenant compte des cas limites et de l'expérience utilisateur.
Pourquoi router.push() n'est pas « Retour »
La méthode router.push() ajoute une nouvelle entrée à l'historique du navigateur. Elle est conçue pour naviguer vers l'avant vers une nouvelle route, même si cette route a déjà été visitée. Contrairement à elle, router.back() et router.go(-1) ne créent pas de nouvelles entrées : elles déplacent simplement le pointeur dans la pile d'historique existante.
Lorsque vous utilisez router.push() pour le bouton « Retour », vous simulez en réalité une navigation vers l'avant, déguisée en retour. Cela mène à la séquence suivante :
- Utilisateur : Accueil → Liste des produits → Produit A
- Clique sur votre bouton « Retour » avec
router.push('/list') - L'historique devient : Accueil → Liste des produits → Produit A → Liste des produits (duplicata)
Désormais, si l'utilisateur clique sur le bouton Retour du navigateur, il retournera à la page « Produit A », et non à « Accueil ». Un nouveau clic sur votre bouton déclenchera un push supplémentaire, et le cycle continue.
Méthodes principales de navigation dans Vue Router
Vue Router fournit trois méthodes clés pour gérer l'historique :
router.push(location)— ajoute une nouvelle entrée à l'historique.router.replace(location)— remplace l'entrée actuelle sans en ajouter une nouvelle.router.back()/router.go(-1)— remonte dans l'historique existant.
Pour le bouton « Retour » dans l'interface, le seul choix correct est router.back() ou router.go(-1). Elles correspondent parfaitement au comportement du bouton du navigateur et ne violent pas l'intégrité de la pile.
Gestion des cas limites : Quand il n'y a pas d'historique
En pratique, les utilisateurs atterrissent souvent directement sur une page — via un lien externe, un rafraîchissement de page ou après avoir fermé un onglet. Dans ces cas, la pile d'historique peut être vide ou ne contenir qu'une seule entrée. Appeler router.back() ne génère pas d'erreur, mais rien ne se passe, laissant l'utilisateur en plan.
Pour éviter cela, fournissez une route de secours (fallbackRoute). La logique doit vérifier si la navigation arrière est possible et, sinon, rediriger vers une route sûre — par exemple, la page d'accueil ou la section parente.
Composant universel de bouton « Retour »
Voici un composant prêt pour la production qui gère tous les scénarios nécessaires :
<script setup lang="ts">
import { computed } from 'vue'
import { useRouter, useRoute, type RouteLocationRaw } from 'vue-router'
const props = defineProps<{
fallbackRoute?: RouteLocationRaw
beforeNavigate?: () => boolean | Promise<boolean>
beforeRouterPush?: () => void
}>()
const router = useRouter()
const route = useRoute()
const isSamePage = computed<boolean>(() => {
const fromRoute = router.options.history.state?.back
if (!fromRoute || typeof fromRoute !== 'string') return false
const currentPrefix = route.path.split('/')[1]
const fromPrefix = fromRoute.split('/')[1]
return currentPrefix === fromPrefix
})
const goBack = async () => {
if (props.beforeNavigate) {
const shouldProceed = await props.beforeNavigate()
if (!shouldProceed) return
}
if (props.beforeRouterPush) {
props.beforeRouterPush()
return
}
if (isSamePage.value) {
router.back()
} else if (props.fallbackRoute) {
void router.push(props.fallbackRoute)
} else {
void router.push({ name: 'home' })
}
}
</script>
<template>
<q-btn
icon="arrow_back"
@click="goBack"
aria-label="Onzad"
/>
</template>
Ce composant résout plusieurs tâches en même temps :
- Supporte la confirmation avant de quitter (par ex., sauvegarder un brouillon)
- Distingue les transitions internes et externes par les préfixes d'URL
- Fournit une route de secours
- Permet de surcharger complètement la logique si nécessaire
Points clés
- N'utilisez pas
router.push()pour le bouton « Retour » — cela viole le modèle d'historique du navigateur. - Fournissez toujours un comportement de secours pour les cas d'accès direct.
- Vérifiez le contexte de transition : un retour au sein d'une section et un retour depuis l'extérieur nécessitent une logique différente.
- Supportez l'annulation de navigation via des hooks asynchrones — crucial pour les formulaires et éditeurs.
- Synchronisez le comportement avec le bouton Retour natif du navigateur — l'utilisateur ne doit pas remarquer de différence.
— Editorial Team
Aucun commentaire pour le moment.