React

Guardie di navigazione in Vue Router: ordine e valori di ritorno

In Vue Router 4 una guardia restituisce un valore: false blocca, una rotta reindirizza, niente prosegue. L’ordine decide quale vince.

In sintesi

  • Una guardia in Vue Router 4 restituisce un valore; next() è facoltativo.
  • L’ordine è beforeEach, beforeEnter, beforeRouteEnter, beforeResolve, afterEach.
  • Le guardie proteggono la navigazione, non i dati: il controllo server resta necessario.

Una guardia di navigazione in Vue Router 4 restituisce un valore: false annulla la navigazione, una rotta la reindirizza, nessun valore la lascia passare. La forma con next() resta supportata, ma mescolare le due nello stesso file è la causa più comune di redirect infiniti.

Ordine di esecuzione

FaseDove si dichiaraCosa può fare
beforeEachrouter.beforeEachBloccare o reindirizzare ogni navigazione
beforeEnterSulla rottaVale solo per quella rotta
beforeRouteEnterNel componenteEntrare senza accesso a this
beforeResolverouter.beforeResolveUltimo controllo prima della conferma
afterEachrouter.afterEachSolo effetti: analytics, titolo

L’ordine è quello della tabella. Conoscerlo evita il caso classico: lo stesso controllo di autenticazione scritto in beforeEach e in beforeEnter, che gira due volte senza motivo.

Autenticazione senza incoerenze

router.beforeEach(async (to) => {
  const session = await getSession();
  if (!session && to.meta.requiresAuth) {
    return { name: "login", query: { next: to.fullPath } };
  }
  if (session && to.name === "login") {
    return { name: "dashboard" };
  }
});

La seconda condizione è quella che manca quasi sempre. Senza di essa un utente già autenticato può aprire la pagina di login: non è un loop, è uno stato incoerente che confonde chi sta usando l’app.

Bloccare l’uscita da un form

import { onBeforeRouteLeave } from "vue-router";

const dirty = ref(false);
onBeforeRouteLeave(() => {
  if (!dirty.value) return true;
  return window.confirm("Uscire senza salvare?");
});

onBeforeRouteLeave vale solo per il componente che lo dichiara. Restituire false annulla la navigazione e l’URL non cambia.

Errori che si vedono in produzione

  • Guardia registrata dentro setup(): si aggiunge un listener a ogni montaggio.
  • next() chiamato due volte nella stessa guardia: la seconda chiamata viene ignorata con un avviso.
  • Redirect verso la rotta protetta senza controllare la sessione: loop.
  • Guardia asincrona senza await sulla sessione: la decisione arriva dopo la navigazione.

Il limite noto

Le guardie proteggono la navigazione, non i dati. Un client può chiamare l’API direttamente: ogni rotta protetta ha bisogno anche di un controllo sul server. La guardia serve all’interfaccia, non alla sicurezza.

Comandi

npm install vue-router@4
npx vue-tsc --noEmit

Dal catalogo: shadcn-vue, vue-bits e il blocco logo Vue. Le guide: le librerie UI per Vue 3 e la struttura di un progetto Nuxt 3; il confronto: Vue contro React nel 2026.

Domande frequenti

next() è ancora supportato?

Sì, ma conviene scegliere una forma sola. In una guardia asincrona restituisci il valore e non chiamare next.

Perché la mia guardia non vede lo store alla prima visita?

Perché gira prima del mount dell’app. Aspetta router.isReady() oppure inizializza lo store prima del mount.

Come faccio un redirect permanente?

Con una regola in createRouter, non con una guardia. La guardia girerebbe a ogni navigazione e aggiungerebbe lavoro inutile.

beforeRouteEnter è diverso da beforeEnter?

Sì. beforeEnter è una proprietà della rotta, beforeRouteEnter è un hook del componente e non ha accesso a this.

Posso annullare il tasto Indietro?

Sì, restituendo false da onBeforeRouteLeave sul componente attivo. Non puoi bloccare la chiusura della scheda.