Vue Router es una muy buena solución para armar aplicaciones SPA, pero ¿cómo hace para resolver situaciones en las que necesitamos hacer redireccionamientos automáticos o cancelar una redirección, por ejemplo, para prevenir el acceso de un usuario no autenticado a una URL específica?
Aquí es donde entran en efecto las guardas de navegación. Vue Router nos permite especificar reglas para las redirecciones conocidas como guardas. Esto es necesario porque para el navegador, las SPA siempre permanecen en la misma página, ya que los cambios de página que vamos viendo son en realidad cambios de renderizado de un componente a otro.
Router nos provee de diversos tipos de guarda y hooks relacionados con el proceso de redirección. A continuación les presento el flujo completo del proceso de redirección, para ver en más detalle en qué momento entra en juego cada guarda y cuando se disparan los eventos que interceptamos con los hooks:
Es importante notar que los cambios en los query params no invocan las guardas de navegación globales. Para reaccionar a esos cambios, se pueden usar las guardas beforeRouteUpdate propias de cada componente o se puede poner un watch en el objeto $route.
Guardas globales
En Router, tenemos tres categorías de guardas: globales, de ruta y de componente. Las globales se definen pasando funciones como la siguiente a los objetos beforeEach, beforeResolve y afterEach del objeto Router:
Como podemos ver, la guarda recibe tres parámetros, to, from y next:
- to (objeto de tipo Route): es el componente hacia el que estamos navegando.
- from (objeto de tipo Route): es el componente desde el que estamos navegando.
- next (función): es necesario invocar esta función para resolver la redirección. La acción que router va a tomar depende del parámetro que pasemos:
- next(): Procesar el siguiente hook del flujo. Si no quedan más hooks, se confirma la navegación.
- next(false): Abortar la navegación. Si ya se había cambiado la URL (manualmente o mediante los botones atrás o adelante del navegador), se vuelve a mostrar la URL del componente from.
- next('/ruta/a/un/componente') o next({ path: 'ruta/a/componente' }): redirige a la dirección especificada. Se aborta la navegación actual y se inicia una nueva. Se puede pasar cualquier objeto de ubicación a esta función.
- next(error): Si pasamos un objeto Error a la función next(), se aborta la navegación y se pasa el error a la función definida en el callback router.onError().
Veamos un ejemplo de una guarda que redirige al usuario al login si no está autenticado, o continua con la navegación actual en caso de que sí lo esté:
Hook afterEach
El hook afterEach es diferente a los anteriores porque se invoca cuando la navegación ya se confirmó. Por ese motivo, no puede afectarla, y por lo tanto no recibe una función next():
Guardas de ruta
Las guardas de ruta se escriben directamente en cada regla de router, en el objeto de configuración que le pasamos cuando creamos la instancia. A modo de ejemplo, en el siguiente fragmento nos aseguramos de que el ID de usuario enviado sea mayor que cero; de lo contrario, redirigimos a la página de error:
Guardas de componente
Como su nombre lo sugiere, las guardas de componente se escriben directamente en los componentes de ruteo que vamos a mostrar cuando nos dirijamos a las distintas direcciones de nuestra SPA. Para ello, hacemos uso de tres hooks:
- beforeRouteEnter: Nos permite ejecutar acciones antes de que se ingrese a la ruta que instancia este componente. Hay que tener en cuenta que dentro de esta función, no tenemos acceso al objeto "this", ya que el componente aún no se instanció.
- beforeRouteUpdate: Nos permite ejecutar acciones cuando cambia la ruta, pero este componente se sigue renderizando en la nueva ruta. Por ejemplo, si tomamos el ejemplo de la imagen anterior (/user/:userId), se llamaría a este hook si cambiamos de /user/1 a /user/2. En este caso, sí tenemos acceso al objeto this.
- beforeRouteLeave: Nos permite ejecutar acciones cuando se cambia a una ruta que no incluye este componente. Tiene acceso al objeto this.
Para tener en claro cómo se utilizarían estos hooks en un componente, veamos el siguiente ejemplo:
Esperamos que esta breve introducción arroje algo de luz sobre las guardas de navegación de router, una función poderosa y hasta vital para el funcionamiento de nuestra SPA. ¡Saludos y nos vemos en el próximo artículo!