El Atributo ONPAGEHIDE

El atributo onpagehide se dispara cuando el usuario abandona la página.

El atributo onpagehide se dispara cuando el usuario abandona la página, ya sea por:

  • Navegar a otra página

  • Cerrar la pestaña/ventana

  • Actualizar la página

  • Usar el botón "Atrás/Adelante"

Es parte de la Page Visibility API y complementa otros eventos como onunload y onbeforeunload.

Sintaxis Básica

HTML:

<body onpagehide="miFuncion(event)">

JavaScript:

window.addEventListener('pagehide', (event) => {
    // Lógica aquí
});

Ejemplos Clave

Ejemplo 1: Autoguardado de Progreso

JavaScript:

function manejarSalidaPagina() {
    localStorage.setItem('autoSaveContent', editor.value);
}

Ejemplo 2: Análisis de Tiempo en Página

JavaScript:

let startTime = Date.now();

function manejarSalidaPagina() {
    const tiempoSesion = Date.now() - startTime;
    enviarMetricasAlServidor(tiempoSesion);
}

Ejemplo 3: Control de Cambios no Guardados

JavaScript:

if(unsavedChanges) {
    event.preventDefault();
    mostrarConfirmacion();
}

Propiedades Importantes

event.persisted: Indica si la página está en caché (útil para navegación con bfcache)

JavaScript:

if(event.persisted) {
    // La página está siendo almacenada en caché
}

Diferencias con Eventos Similares

Evento Momento de Activación ¿Se puede cancelar?
onpagehide Cuando la página comienza a ocultarse Sí (con limitaciones)
onbeforeunload Antes de descargar la página
onunload Cuando la página se está descargando No

Buenas Prácticas

Optimiza el rendimiento:

JavaScript:

event.preventDefault(); // Usar solo cuando sea necesario

Manejo asíncrono:

JavaScript:

event.waitUntil(
    new Promise((resolve) => {
        // Operaciones asíncronas
        resolve();
    })
);

Limpia recursos:

JavaScript:

clearInterval(intervalID);
websocket.close();

Prueba con bfcache:

JavaScript:

window.addEventListener('pageshow', (event) => {
    if(event.persisted) {
        // La página fue restaurada desde el caché
    }
});

Casos de Uso Avanzados

  • Recuperación de sesión: Guardar estado de aplicaciones complejas

  • Optimización de rendimiento: Liberar memoria antes de salir

  • Análisis de usuario: Registrar patrones de navegación

  • Sincronización final: Enviar última versión de datos al servidor

Compatibilidad

Navegador Soporte
Chrome ✅ 24+
Firefox ✅ 10+
Safari ✅ 7+
Edge ✅ 17+

Conclusión

El atributo onpagehide es esencial para:

  • Mejorar la persistencia de datos

  • Optimizar el rendimiento

  • Proporcionar retroalimentación al usuario

  • Recopilar métricas importantes

Implementa siempre:

  • Manejo de operaciones asíncronas

  • Limpieza adecuada de recursos

  • Comprobación del estado persisted

 JavaScript:

<!-- Ejemplo Final: Gestión de Recursos -->
<script>
let recursos = [];

function cargarRecurso(url) {
    const recurso = new HeavyResource(url);
    recursos.push(recurso);
}

window.addEventListener('pagehide', () => {
    recursos.forEach(recurso => recurso.liberar());
    recursos = [];
});
</script>

Este tutorial te proporciona las bases para manejar eficientemente la salida de usuarios en tus aplicaciones web. ¡Experimenta y crea experiencias más robustas!

HTML:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Tutorial: Uso del atributo "onpagehide"</title>
    <style>
        .session-box {
            border: 2px solid #3498db;
            padding: 20px;
            margin: 20px;
            border-radius: 8px;
        }
        #activityLog {
            height: 150px;
            overflow-y: auto;
            padding: 10px;
            background-color: #f8f9fa;
            border: 1px solid #ddd;
        }
        .warning {
            color: #e74c3c;
            font-weight: bold;
        }
    </style>
</head>
<body onpagehide="manejarSalidaPagina(event)">
    <h1>Tutorial del atributo <code>onpagehide</code></h1>

    <!-- Ejemplo 1: Guardar progreso -->
    <div class="session-box">
        <h2>1. Guardado automático de progreso</h2>
        <textarea id="editor" placeholder="Escribe aquí..." rows="5"></textarea>
        <p>Último guardado: <span id="lastSave">Nunca</span></p>
    </div>

    <!-- Ejemplo 2: Registro de actividad -->
    <div class="session-box">
        <h2>2. Registro de tiempo en página</h2>
        <div id="activityLog"></div>
        <p>Tiempo activo: <span id="activeTime">0</span> segundos</p>
    </div>

    <!-- Ejemplo 3: Advertencia de cambios no guardados -->
    <div class="session-box">
        <h2>3. Control de cambios no guardados</h2>
        <form id="mainForm">
            <input type="text" placeholder="Nombre" id="nombre">
            <button type="button" onclick="guardarCambios()">Guardar</button>
        </form>
        <p id="unsavedWarning" class="warning" style="display: none;">
            ¡Tienes cambios no guardados!
        </p>
    </div>

    <script>
        // Variables de estado
        let startTime = Date.now();
        let unsavedChanges = false;
        let autoSaveInterval;

        // Ejemplo 1: Sistema de autoguardado
        const editor = document.getElementById('editor');
        const lastSaveElement = document.getElementById('lastSave');

        function guardarProgreso() {
            localStorage.setItem('autoSaveContent', editor.value);
            lastSaveElement.textContent = new Date().toLocaleTimeString();
        }

        // Ejemplo 2: Registro de tiempo
        function actualizarTiempoActivo() {
            const elapsed = Math.floor((Date.now() - startTime) / 1000);
            document.getElementById('activeTime').textContent = elapsed;
        }

        // Ejemplo 3: Control de cambios
        document.getElementById('mainForm').addEventListener('input', () => {
            unsavedChanges = true;
            document.getElementById('unsavedWarning').style.display = 'block';
        });

        function guardarCambios() {
            unsavedChanges = false;
            document.getElementById('unsavedWarning').style.display = 'none';
        }

        // Manejador principal de pagehide
        function manejarSalidaPagina(event) {
            // Ejemplo 1: Guardar contenido automáticamente
            guardarProgreso();

            // Ejemplo 2: Registrar tiempo final
            const tiempoFinal = Math.floor((Date.now() - startTime) / 1000);
            logActividad(`Sesión finalizada - Duración: ${tiempoFinal}s`);

            // Ejemplo 3: Advertencia de cambios no guardados
            if(unsavedChanges && !event.persisted) {
                event.preventDefault();
                const confirmacion = confirm('¡Tienes cambios no guardados! ¿Seguro que quieres salir?');
                if(!confirmacion) return;
            }

            // Limpiar recursos
            clearInterval(autoSaveInterval);
        }

        // Función auxiliar para registro de actividad
        function logActividad(mensaje) {
            const log = document.getElementById('activityLog');
            log.innerHTML += `<div>${new Date().toLocaleTimeString()}: ${mensaje}</div>`;
            log.scrollTop = log.scrollHeight;
        }

        // Inicialización
        window.addEventListener('load', () => {
            // Cargar contenido guardado
            if(localStorage.getItem('autoSaveContent')) {
                editor.value = localStorage.getItem('autoSaveContent');
            }

            // Configurar intervalos
            autoSaveInterval = setInterval(guardarProgreso, 10000);
            setInterval(actualizarTiempoActivo, 1000);

            logActividad('Sesión iniciada');
        });

        // Manejar eventos de visibilidad
        document.addEventListener('visibilitychange', () => {
            if(document.visibilityState === 'hidden') {
                logActividad('Página oculta');
            } else {
                logActividad('Página visible');
            }
        });
    </script>
</body>
</html>