Tutoriales de Informática y Dispositivos Móviles
Tutoriales de Informática y Dispositivos Móviles
Detectar salida de página javascript

Evento al salir de la página en JavaScript

El evento al salir de la página en JavaScript (beforeunload)

Controlar el momento en que un usuario decide abandonar tu sitio web es fundamental para evitar la pérdida de datos, como cuando un usuario cierra la pestaña a mitad de rellenar un formulario largo. En este tutorial, exploraremos cómo funciona el evento beforeunload, sus severas (pero necesarias) restricciones modernas y cómo implementarlo correctamente.

1. El ciclo de vida de una página HTML

Para entender cuándo y cómo actuar, primero debemos ubicar este momento dentro del ciclo de vida de una página web. El navegador pasa por tres estados clave representados por eventos:

  • DOMContentLoaded: El HTML se ha cargado por completo y el árbol DOM está listo, pero recursos externos como imágenes u hojas de estilo aún pueden estar pendientes.
  • load: La página y todos sus recursos (imágenes, CSS, etc.) se han cargado por completo.
  • beforeunload / unload: El usuario está a punto de abandonar o ya ha abandonado la página.

2. Detectar cuando el usuario se va: beforeunload

El evento beforeunload se dispara en el objeto window justo antes de que los recursos de la página comiencen a descargarse debido a que el usuario cierra la pestaña, recarga la web o navega hacia otro enlace.

Ejemplo 1: El método moderno y compatible

Para activar la ventana de confirmación del navegador, debemos interactuar con el evento de una forma muy específica. Aunque parezca intuitivo usar event.preventDefault(), la gran mayoría de los navegadores modernos ignoran esta instrucción en este evento en particular.

Para que funcione de forma consistente en todos los navegadores, debemos asignar un valor a event.returnValue y, por compatibilidad con navegadores antiguos, retornar una cadena de texto:

JavaScript

JavaScript

window.addEventListener("beforeunload", (event) => {
    // 1. Cancelamos el evento de forma estándar asignando una cadena a returnValue
    event.returnValue = "Hay cambios sin guardar.";

    // 2. Por compatibilidad histórica con navegadores antiguos, también retornamos el texto
    return "Hay cambios sin guardar.";
});

3. ¡Cuidado! Las limitaciones de personalización

En el pasado, los desarrolladores abusaban de este evento mostrando mensajes engañosos o publicidad molesta cuando el usuario intentaba salir. Por este motivo, los navegadores modernos han capado casi por completo su personalización:

  • No puedes cambiar el texto: Da igual la frase que escribas en el return o en returnValue, el navegador la ignorará por completo. En su lugar, mostrará un mensaje genérico del sistema (por ejemplo: «¿Quieres salir de este sitio web? Es posible que los cambios no se guarden»).
  • No puedes personalizar los botones: Los botones de «Salir» y «Permanecer» los renderiza el sistema operativo o el navegador y no se pueden modificar con CSS ni JS.
  • No puedes saber directamente qué eligió el usuario: No hay un evento nativo que te diga si el usuario hizo clic en «Permanecer».

El truco del temporizador para saber si se quedó:

Aunque no hay un callback directo para el botón «Permanecer», puedes usar un truco asíncrono. Al dispararse beforeunload, inicias un temporizador (setTimeout). Si el usuario decide irse, la página se destruirá y el temporizador nunca se ejecutará. Si decide quedarse, el temporizador se ejecutará tras unos segundos en segundo plano, permitiéndote saber indirectamente que el usuario canceló la salida:

JavaScript

window.addEventListener("beforeunload", () => {
    setTimeout(() => {
        console.log("El usuario decidió quedarse en la página");
        // Aquí puedes ejecutar acciones reactivas
    }, 1000);
    event.returnValue = "";
});

4. Resumen de buenas prácticas

  • Solo actívalo cuando sea necesario: No mantengas este evento activo todo el tiempo; resulta molesto si el usuario solo está navegando de forma normal. Actívalo únicamente cuando detectes que un formulario ha sido modificado (dirty) y bórralo cuando el formulario sea enviado con éxito.
  • Evita llamadas asíncronas pesadas: No intentes hacer peticiones de red normales (fetch o axios) pesadas dentro de beforeunload o unload, ya que el navegador podría cerrarse antes de completarse. Para enviar estadísticas de salida de forma segura, utiliza navigator.sendBeacon().

5. Resumen del Ciclo de Vida y Eventos

Evento¿Cuándo se activa?¿Se puede cancelar/frenar?Uso recomendado
DOMContentLoadedDOM listo (sin imágenes/CSS aún).NoInicializar scripts, buscar nodos y configurar la interfaz.
loadPágina y todos sus recursos cargados.NoCalcular tamaños reales de imágenes, aplicar estilos dinámicos.
beforeunloadEl usuario inicia la salida. (vía returnValue)Confirmar si hay cambios sin guardar antes de perderlos.
unloadEl usuario ya se está yendo definitivamente.NoEnviar analíticas o estadísticas de uso rápidas mediante sendBeacon.

Conclusión

El evento beforeunload es tu última línea de defensa para proteger la experiencia de usuario frente a pérdidas accidentales de datos. Aunque los navegadores modernos han restringido la personalización visual de este evento por motivos de seguridad y experiencia de usuario, dominar la sintaxis correcta de returnValue y entender sus limitaciones te ahorrará comportamientos inesperados en producción.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Translate »