0% encontró este documento útil (0 votos)
166 vistas9 páginas

Eventos DOM: beforeunload y unload

El documento describe tres eventos importantes en el ciclo de vida de una página HTML: DOMContentLoaded, load y beforeunload/unload. DOMContentLoaded se dispara cuando el árbol DOM está listo, pero los recursos externos como imágenes aún pueden estar cargando. El evento load se activa cuando se han cargado todos los recursos. Antes de que el usuario abandone la página, se activan beforeunload y luego unload.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
166 vistas9 páginas

Eventos DOM: beforeunload y unload

El documento describe tres eventos importantes en el ciclo de vida de una página HTML: DOMContentLoaded, load y beforeunload/unload. DOMContentLoaded se dispara cuando el árbol DOM está listo, pero los recursos externos como imágenes aún pueden estar cargando. El evento load se activa cuando se han cargado todos los recursos. Antes de que el usuario abandone la página, se activan beforeunload y luego unload.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

 Comprar EPUB/PDF 

ES

 → El navegador: Documentos, Eventos e Interfaces → El documento y carga de recursos

 24 de octubre de 2022

Página: DOMContentLoaded, load,


beforeunload, unload
El ciclo de vida de una página HTML tiene tres eventos importantes:

● DOMContentLoaded – el navegador HTML está completamente cargado y el árbol DOM está


construido, pero es posible que los recursos externos como <img> y hojas de estilo aún no se hayan
cargado.
● load – no solo se cargó el HTML, sino también todos los recursos externos: imágenes, estilos, etc.
● beforeunload/unload – el usuario sale de la pagina.

Cada evento puede ser útil:

● Evento DOMContentLoaded – DOM está listo, por lo que el controlador puede buscar nodos DOM,
inicializar la interfaz.
● Evento load – se cargan recursos externos, por lo que se aplican estilos, se conocen tamaños de
imagen, etc.
● Evento beforeunload – el usuario se va: podemos comprobar si el usuario guardó los cambios y
preguntarle si realmente quiere irse.
● Evento unload – el usuario casi se fue, pero aún podemos iniciar algunas operaciones, como enviar
estadísticas.

Exploremos los detalles de estos eventos.

DOMContentLoaded
El evento DOMContentLoaded ocurre en el objeto document .

Debemos usar addEventListener para capturarlo:

1 [Link]("DOMContentLoaded", ready);
2 // no "[Link] = ..."

Por ejemplo:
 
1 <script>
2 function ready() {
3 alert('DOM is ready');
4
5 // la imagen aún no está cargada (a menos que se haya almacenado en cach
6 alert(`Image size: ${[Link]}x${[Link]}`);
7 }
8
9 [Link]("DOMContentLoaded", ready);
10 </script>
11
12 <img id="img" src="[Link]

En el ejemplo, el controlador del evento DOMContentLoaded se ejecuta cuando el documento está


cargado, por lo que puede ver todos los elementos, incluido el <img> que está después de él.

Pero no espera a que se cargue la imagen. Entonces, alert muestra los tamaños en cero.

A primera vista, el evento DOMContentLoaded es muy simple. El árbol DOM está listo – aquí está el
evento. Sin embargo, hay algunas peculiaridades.

DOMContentLoaded y scripts

Cuando el navegador procesa un documento HTML y se encuentra con una etiqueta <script> , debe
ejecutarla antes de continuar construyendo el DOM. Esa es una precaución, ya que los scripts pueden querer
modificar el DOM, e incluso hacer [Link] en él, por lo que DOMContentLoaded tiene que
esperar.

Entonces DOMContentLoaded siempre ocurre después de tales scripts:

 
1 <script>
2 [Link]("DOMContentLoaded", () => {
3 alert("DOM listo!");
4 });
5 </script>
6
7 <script src="[Link]
8
9 <script>
10 alert("Libreria cargada, linea de script ejecutada");
11 </script>

En el ejemplo anterior, primero vemos “Biblioteca cargada …” y luego “¡DOM listo!” (se ejecutan todos los
scripts).
 Scripts que no bloquean DOMContentLoaded
Hay dos excepciones a esta regla:

1. Scripts con el atributo async , que cubriremos un poco más tarde, no bloquea el
DOMContentLoaded .
2. Los scripts que se generan dinámicamente con [Link]('script') y luego
se agregan a la página web, tampoco bloquean este evento.

DOMContentLoaded y estilos

Las hojas de estilo externas no afectan a DOM, por lo que DOMContentLoaded no las espera.

Pero hay una trampa. Si tenemos un script después del estilo, entonces ese script debe esperar hasta que se
cargue la hoja de estilo:

 
1 <link type="text/css" rel="stylesheet" href="[Link]">
2 <script>
3 // el script no se ejecuta hasta que se cargue la hoja de estilo
4 alert(getComputedStyle([Link]).marginTop);
5 </script>

La razón de esto es que el script puede querer obtener coordenadas y otras propiedades de elementos
dependientes del estilo, como en el ejemplo anterior. Naturalmente, tiene que esperar a que se carguen los
estilos.

Como DOMContentLoaded espera los scripts, ahora también espera a los estilos que están antes que ellos.

Autocompletar del navegador integrado

Firefox, Chrome y Opera autocompletan formularios en DOMContentLoaded .

Por ejemplo, si la página tiene un formulario con nombre de usuario y contraseña, y el navegador recuerda
los valores, entonces en DOMContentLoaded puede intentar completarlos automáticamente (si el usuario
lo aprueba).

Entonces, si DOMContentLoaded es pospuesto por scripts de largo tiempo de carga, el autocompletado


también espera. Probablemente haya visto eso en algunos sitios (si usa la función de autocompletar del
navegador): los campos de inicio de sesión/contraseña no se autocompletan inmediatamente, sino con
retraso hasta que la página se carga por completo. En realidad es el retraso hasta el evento
DOMContentLoaded .

[Link]
El evento load en el objeto window se activa cuando se carga toda la página, incluidos estilos, imágenes
y otros recursos. Este evento está disponible a través de la propiedad onload .
El siguiente ejemplo muestra correctamente los tamaños de las imágenes, porque [Link] espera
todas las imágenes:

 
1 <script>
2 [Link] = function() { // también puede usar [Link]
3 alert('Página cargada');
4
5 // la imagen es cargada al mismo tiempo
6 alert(`Tamaño de imagen: ${[Link]}x${[Link]}`);
7 };
8 </script>
9
10 <img id="img" src="[Link]

[Link]
Cuando un visitante abandona la página, el evento unload se activa en window . Podemos hacer algo allí
que no implique un retraso, como cerrar ventanas emergentes relacionadas.

La excepción notable es el envío de análisis.

Supongamos que recopilamos datos sobre cómo se usa la página: clicks del mouse, desplazamientos, áreas
de página visitadas, etc.

Naturalmente, el evento unload sucede cuando el usuario nos deja y nos gustaría guardar los datos en
nuestro servidor.

Existe un método especial [Link](url, data) para tales necesidades, descrito en la


especificación [Link]

Este envía los datos en segundo plano. La transición a otra página no se retrasa: el navegador abandona la
página, pero aún realiza sendBeacon .

Así es como se usa:

1 let analyticsData = { /* objeto con datos recopilados */ };


2
3 [Link]("unload", function() {
4 [Link]("/analytics", [Link](analyticsData));
5 });

● La solicitud se envía como POST.


● Podemos enviar no solo una cadena, sino también formularios y otros formatos, como se describe en el
capítulo <info: fetch>, pero generalmente es un objeto string.
● Los datos están limitados por 64 kb.

Cuando finaliza la solicitud sendBeacon , es probable que el navegador ya haya abandonado el documento,
por lo que no hay forma de obtener la respuesta del servidor (que suele estar vacía para análisis).
También hay una bandera keepalive para hacer tales solicitudes “after-page-left” en el método [fetch]
(info: fetch) para solicitudes de red genéricas. Puede encontrar más información en el capítulo <info: fetch-
api>.

Si queremos cancelar la transición a otra página, no podemos hacerlo aquí. Pero podemos usar otro evento:
onbeforeunload .

[Link]
Si un visitante inició la navegación fuera de la página o intenta cerrar la ventana, el controlador
beforeunload solicita una confirmación adicional.

Si cancelamos el evento, el navegador puede preguntar al visitante si está seguro.

Puede probarlo ejecutando este código y luego recargando la página:

 
1 [Link] = function() {
2 return false;
3 };

Por razones históricas, devolver una cadena no vacía también cuenta como cancelar el evento. Hace algún
tiempo, los navegadores solían mostrarlo como un mensaje, pero como dice la especificación moderna, no
deberían.

Aquí hay un ejemplo:

 
1 [Link] = function() {
2 return "Hay cambios sin guardar. ¿Salir ahora?";
3 };

El comportamiento se modificó, porque algunos webmasters abusaron de este controlador de eventos


mostrando mensajes engañosos y molestos. Entonces, en este momento, los navegadores antiguos aún
pueden mostrarlo como un mensaje, pero aparte de eso, no hay forma de personalizar el mensaje que se
muestra al usuario.
 El [Link]() no funciona desde un manejador
beforeunload
Esto puede sonar extraño, pero la mayoría de los navegadores ignoran [Link]() .

Lo que significa que el siguiente código puede no funcionar:

 
1 [Link]("beforeunload", (event) => {
2 // no funciona, así que el manejador de evento no hace nada
3 [Link]();
4 });

En lugar de ello, en tales manejadores uno debe establecer [Link] a un string para
obtener un resultado similar al pretendido en el código de arriba:

 
1 [Link]("beforeunload", (event) => {
2 // funciona, lo mismo que si devolviera desde [Link]
3 [Link] = "Hsy cambios sin grabar. ¿Abandonar ahora?";
4 });

readyState
¿Qué sucede si configuramos el controlador DOMContentLoaded después de cargar el documento?

Naturalmente, nunca se ejecutará.

Hay casos en los que no estamos seguros de si el documento está listo o no. Nos gustaría que nuestra
función se ejecute cuando se cargue el DOM, ya sea ahora o más tarde.

La propiedad [Link] nos informa sobre el estado de carga actual.

Hay 3 valores posibles:

● "loading" – el documento se está cargando.


● "interactive" – el documento fue leído por completo.
● "complete" – el documento se leyó por completo y todos los recursos (como imágenes) también se
cargaron.

Entonces podemos verificar [Link] y configurar un controlador o ejecutar el código


inmediatamente si está listo.

Como esto:
1 function work() { /*...*/ }
2
3 if ([Link] == 'loading') {
4 // cargando todavía, esperar el evento
5 [Link]('DOMContentLoaded', work);
6 } else {
7 // DOM está listo!
8 work();
9 }

También existe el evento readystatechange que se activa cuando cambia el estado, por lo que podemos
imprimir todos estos estados así:

 
1 // estado actual
2 [Link]([Link]);
3
4 //imprimir los cambios de estado
5 [Link]('readystatechange', () => [Link](document

El evento readystatechange es una mecánica alternativa para rastrear el estado de carga del
documento, apareció hace mucho tiempo. Hoy en día, rara vez se usa.

Veamos el flujo de eventos completo para ver si están completados.

Aquí hay un documento con <iframe> , <img> y controladores que registran eventos:

1 <script>
2 log('initial readyState:' + [Link]);
3
4 [Link]('readystatechange', () => log('readyState:'
5 [Link]('DOMContentLoaded', () => log('DOMContentLoaded'
6
7 [Link] = () => log('window onload');
8 </script>
9
10 <iframe src="[Link]" onload="log('iframe onload')"></iframe>
11
12 <img src="[Link] id="img">
13 <script>
14 [Link] = () => log('img onload');
15 </script>

El ejemplo práctico está en el sandbox.

La salida típica:

1. [1] readyState inicial: loading


2. [2] readyState: interactive
3. [2] DOMContentLoaded
4. [3] iframe onload
5. [4] img onload
6. [4] readyState: complete
7. [4] window onload

Los números entre corchetes denotan el tiempo aproximado en el que ocurre. Los eventos etiquetados con el
mismo dígito ocurren aproximadamente al mismo tiempo (+ – unos pocos ms).

● [Link] se convierte en interactive justo antes de DOMContentLoaded . Estas


dos cosas realmente significan lo mismo.
● [Link] se convierte en complete cuando se cargan todos los recursos ( iframe e
img ). Aquí podemos ver que ocurre aproximadamente al mismo tiempo que [Link] ( img es el
último recurso) y [Link] . Cambiar al estado complete significa lo mismo que
“[Link]”. La diferencia es que [Link] siempre funciona después de todos los demás
controladores load .

Resumen
Eventos de carga de página:

● El evento DOMContentLoaded se activa en el document cuando el DOM está listo. Podemos aplicar
JavaScript a elementos en esta etapa.
● Secuencias de comandos como <script> ... </script> o <script src =" ... "> </
script> bloquean DOMContentLoaded, el navegador espera a que se ejecuten.
● Las imágenes y otros recursos también pueden seguir cargándose.
● El evento load en window se activa cuando se cargan la página y todos los recursos. Rara vez lo
usamos, porque generalmente no hay necesidad de esperar tanto.
● El evento beforeunload en window se activa cuando el usuario quiere salir de la página. Si
cancelamos el evento, el navegador pregunta si el usuario realmente quiere irse (por ejemplo, tenemos
cambios sin guardar).
● El evento unload en window se dispara cuando el usuario finalmente se está yendo, en el controlador
solo podemos hacer cosas simples que no impliquen demoras o preguntas al usuario. Debido a esa
limitación, rara vez se usa. Podemos enviar una solicitud de red con [Link] .
● [Link] es el estado actual del documento, los cambios se pueden rastrear con el
evento readystatechange :
● loading – el documento esta cargando.
● interactive – el documento se analiza, ocurre aproximadamente casi al mismo tiempo que
DOMContentLoaded , pero antes.
● complete – el documento y los recursos se cargan, ocurre aproximadamente casi al mismo tiempo
que [Link] , pero antes.

 Lección anterior Próxima lección



Compartir    Mapa del Tutorial

 Comentarios

● Si tiene sugerencias sobre qué mejorar, por favor enviar una propuesta de GitHub o una solicitud
de extracción en lugar de comentar.
● Si no puede entender algo en el artículo, por favor explique.
● Para insertar algunas palabras de código, use la etiqueta <code> , para varias líneas –
envolverlas en la etiqueta <pre> , para más de 10 líneas – utilice una entorno controlado
(sandbox) (plnkr, jsbin, codepen…)

© 2007—2024 Ilya Kantoracerca del proyecto


contáctenos

También podría gustarte