Volver al inicio

Botón Atrás en Vue: Implementación Correcta

Guía Técnica para la Implementación Correcta del Botón Atrás en Aplicaciones Vue.js. Se Analizan Errores en el Uso de router.push(), Se Proponen Soluciones para Casos Límite y un Componente Universal con Fallback y Confirmación.

Botón Atrás en Vue: Problemas y Solución
Advertisement 728x90

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:

Google AdInline article slot
  • 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.

Google AdInline article slot

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:

Google AdInline article slot
<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

Advertisement 728x90

Leer después