Cómo implementar correctamente el botón 'Atrás' en Vue: Guía técnica para desarrolladores
La implementación del botón 'Atrás' en aplicaciones Vue.js a menudo parece sencilla, pero en la práctica, provoca serios problemas de navegación e historial del navegador. Muchos desarrolladores cometen el error de usar router.push() en lugar de métodos diseñados para moverse a través del stack de historial existente. Esto crea entradas duplicadas, rompe el comportamiento del botón Atrás del navegador y forma bucles de transición infinitos. Este artículo proporciona una guía técnicamente precisa para implementar correctamente el botón 'Atrás', teniendo en cuenta casos límite y la experiencia del usuario.
Por qué router.push() no es 'Atrás'
El método router.push() añade una nueva entrada al historial del navegador. Está diseñado para navegar hacia adelante a una nueva ruta, incluso si esa ruta ya se visitó antes. A diferencia de él, router.back() y router.go(-1) no crean nuevas entradas: simplemente mueven el puntero a través del stack de historial existente.
Cuando usas router.push() para el botón 'Atrás', en realidad estás simulando una navegación hacia adelante, disfrazándola de regreso. Esto lleva a la siguiente secuencia:
- Usuario: Inicio → Lista de productos → Producto A
- Hace clic en tu botón 'Atrás' con
router.push('/list') - El historial se convierte en: Inicio → Lista de productos → Producto A → Lista de productos (duplicado)
Ahora, si el usuario hace clic en el botón Atrás del navegador, volverá a la página de 'Producto A', no a 'Inicio'. Hacer clic en tu botón de nuevo activará push una vez más, y el ciclo continúa.
Métodos principales de navegación en Vue Router
Vue Router proporciona tres métodos clave para gestionar el historial:
router.push(location)— añade una nueva entrada al historial.router.replace(location)— reemplaza la entrada actual sin añadir una nueva.router.back()/router.go(-1)— se mueve hacia atrás a través del historial existente.
Para el botón 'Atrás' en la interfaz de usuario, la única opción correcta es router.back() o router.go(-1). Coinciden completamente con el comportamiento del botón del navegador y no violan la integridad del stack.
Manejo de casos límite: Cuando no hay historial
En la práctica, los usuarios a menudo llegan a una página directamente: a través de un enlace externo, recarga de página o después de cerrar una pestaña. En estos casos, el stack de historial puede estar vacío o contener solo una entrada. Llamar a router.back() no lanzará un error, pero no pasará nada, dejando al usuario colgado.
Para evitar esto, proporciona una ruta de respaldo (fallbackRoute). La lógica debe verificar si la navegación hacia atrás es posible y, si no, redirigir a una ruta segura: por ejemplo, la página de inicio o la sección principal.
Componente universal de botón 'Atrás'
Aquí tienes un componente listo para producción que soporta todos los escenarios necesarios:
<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>
Este componente resuelve varias tareas a la vez:
- Soporta confirmación antes de salir (p. ej., guardar un borrador)
- Distingue transiciones internas y externas por prefijos de URL
- Proporciona una ruta de respaldo
- Permite sobrescribir completamente la lógica si es necesario
Puntos clave
- No uses
router.push()para el botón 'Atrás' — viola el modelo de historial del navegador. - Proporciona siempre un comportamiento de respaldo para casos de acceso directo.
- Verifica el contexto de la transición: regresar dentro de una sección y desde fuera requieren lógicas diferentes.
- Soporta cancelar la navegación mediante hooks asíncronos — crítico para formularios y editores.
- Sincroniza el comportamiento con el botón Atrás nativo del navegador — el usuario no debería notar diferencia.
— Editorial Team
Aún no hay comentarios.