Mecanismo de propagación de eventos DOM

Mecanismo de propagación de eventos DOM.

Preguntas reales clásicas

  • Hablemos de la delegación de eventos y el principio de burbujeo.

Eventos y transmisiones de eventos

Los eventos aparecieron por primera vez en IE3 y Netscape Navigator2 como una forma de compartir la carga informática del servidor.

Para interactuar con páginas web, necesita utilizar eventos en JavaScript .

Cada vez que un usuario interactúa con una página web, como hacer clic en un enlace, presionar un botón o mover el mouse, se activa un evento. Nuestro programa puede detectar estos eventos y luego responder a ellos. Formando así una interacción.

Esto puede hacer que nuestra página sea más interesante, no sólo para navegar como antes.

En los primeros días del acceso telefónico a Internet, si todas las funciones se procesaran en el lado del servidor, la eficiencia sería muy baja.

Entonces JavaScript fue diseñado originalmente para resolver estos problemas. Ahorre tiempo de ida y vuelta al servidor permitiendo que algunas funciones se manejen en el lado del cliente.

JavaScript utiliza algo llamado detector de eventos para monitorear si ocurren eventos. Este detector de eventos es similar a una notificación: cuando ocurre un evento, el detector de eventos nos lo informará y luego el programa podrá responder en consecuencia.

De esta manera, puede evitar que el programa verifique constantemente si el evento ha ocurrido y permitir que el programa continúe realizando otras tareas mientras espera que ocurra el evento.

flujo de eventos

Cuando el navegador se desarrolló hasta la cuarta generación ( IE4 y Netscape4 ), el equipo de desarrollo del navegador se encontró con una pregunta muy interesante: ¿Qué parte de la página tendrá un evento específico?

Imagine un conjunto de círculos concéntricos en una hoja de papel. Si coloca su dedo en el centro del círculo, su dedo apunta no a un círculo, sino a todos los círculos del papel.

imagen-20211002174941387

Afortunadamente, los equipos de desarrollo de navegadores de las dos empresas todavía ven los eventos del navegador de la misma manera.

Si se hace clic en un botón, todos creen que el evento de clic ocurrió no solo en el botón, sino incluso en toda la página.

Pero lo interesante es que los equipos de desarrollo de IE y Netscape en realidad propusieron conceptos de flujo de eventos casi completamente opuestos.

El flujo de eventos de IE es un flujo de eventos burbujeante, mientras que el flujo de eventos de Netscape es un flujo de captura de eventos.

corriente burbujeante del evento

El flujo de eventos de IE se llama transmisión de eventos , es decir, el evento es recibido inicialmente por el elemento más específico (el nodo con el nivel de anidamiento más profundo en el documento) y luego se propaga hacia arriba a nodos (documentos) menos específicos.

Tome la siguiente estructura HTML como ejemplo para ilustrar la propagación de eventos. como sigue:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div></div>
    </body>
</html>

Si se hace clic en un elemento div de la página , el evento de clic se propaga hacia arriba a lo largo del árbol DOM , ocurre en cada nivel de nodo y se propaga en el siguiente orden:

  1. div
  2. cuerpo
  3. HTML
  4. documento

Todos los navegadores modernos admiten la propagación de eventos, pero existen algunas diferencias en la implementación.

Eventos de burbujas de IE9, Firefox, Chrome y Safari hasta el objeto de ventana.

Podemos usar el siguiente código para ver el orden de difusión específico del documento, el ejemplo es el siguiente:

<div id="box" style="height:100px;width:300px;background-color:pink;"></div>
<button id="reset">还原</button>
// IE8 以下浏览器返回 div body html document
// 其他浏览器返回 div body html document window
reset.onclick = function () {
    
    
  history.go();
}
box.onclick = function () {
    
    
  box.innerHTML += 'div\n';
}
document.body.onclick = function () {
    
    
  box.innerHTML += 'body\n';
}
document.documentElement.onclick = function () {
    
    
  box.innerHTML += 'html\n';
}
document.onclick = function () {
    
    
  box.innerHTML += 'document\n';
}
window.onclick = function () {
    
    
  box.innerHTML += 'window\n';
}

En el ejemplo anterior, hemos vinculado eventos de clic al div y sus elementos antecesores. Debido a la existencia de propagación de eventos, cuando hacemos clic en el div , también se activarán los eventos de clic de todos los elementos antecesores.

Como se muestra abajo:

imagen-20211002172307085

flujo de captura de eventos

Otro flujo de eventos propuesto por el equipo de Netscape Communicator se llama captura de eventos ( event captruing ).

La idea de la captura de eventos es que los nodos menos específicos deberían recibir eventos antes, mientras que los nodos más específicos deberían recibir eventos al final.

La idea de la captura de eventos es capturar el evento antes de que alcance el objetivo previsto.

Tome la misma estructura HTML como ejemplo para ilustrar la captura de eventos, de la siguiente manera:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div></div>    
    </body>
</html>

Durante el proceso de captura de eventos, el objeto del documento primero recibe el evento de clic y luego el evento se propaga hacia abajo a lo largo del árbol DOM hasta que alcanza el objetivo real del evento, que es el elemento div :

  1. documento
  2. HTML
  3. cuerpo
  4. div

Los navegadores modernos como IE9, Firefox, Chrome y Safari admiten la captura de eventos, pero también comienzan a capturar desde el objeto de la ventana .

Demostremos un ejemplo de una secuencia de captura de eventos:

<div id="box" style="height:100px;width:300px;background-color:pink;"></div>
<button id="reset">还原</button>
// IE8 以下浏览器不支持
// 其他浏览器返回 window document html body div
reset.onclick = function () {
    
    
  history.go();
}
box.addEventListener('click', function () {
    
    
  box.innerHTML += 'div\n'
}, true)
document.body.addEventListener('click', function () {
    
    
  box.innerHTML += 'body\n';
}, true);
document.documentElement.addEventListener('click', function () {
    
    
  box.innerHTML += 'html\n';
}, true);
document.addEventListener('click', function () {
    
    
  box.innerHTML += 'document\n';
}, true);
window.addEventListener('click', function () {
    
    
  box.innerHTML += 'window\n';
}, true);

En el ejemplo anterior, vinculamos el evento click al div y todos sus elementos antecesores, usamos el método addEventListener para vincular el evento y configuramos el segundo parámetro en verdadero para usar la captura de eventos para activar el evento.

Resultados como se muestra a continuación:

imagen-20211002173549252

Flujo de eventos DOM estándar

El estándar DOM adopta el método de captura + burbujeo .

Ambos flujos de eventos activarán todos los objetos en el DOM , comenzando y terminando con el objeto del documento .

En otras palabras, el punto inicial y el punto final son objetos de documento (muchos navegadores siempre pueden capturar + burbuja en el objeto de ventana)

Diagrama de flujo de eventos DOM :

imagen-20211002174148423

El estándar DOM estipula que el flujo de eventos incluye tres etapas: etapa de captura de eventos , etapa de destino y etapa de difusión de eventos .

  • **Fase de captura de eventos:** El div objetivo real no activará eventos durante la fase de captura. La fase de captura comienza desde la ventana , luego en el documento, html y finalmente en el cuerpo , lo que significa que la fase de captura finaliza.

  • **En la fase de destino:** El evento ocurre y se procesa en el div , pero este procesamiento de evento se considerará parte de la fase de propagación.

  • **Fase de burbujeo:** El evento se propaga de nuevo al documento.

delegación de eventos

El flujo de difusión de eventos se presentó anteriormente. Uno de los mayores beneficios de la difusión de eventos es que puede implementar la delegación de eventos.

La delegación de eventos también se denomina proxy de eventos. En JavaScript , la cantidad de controladores de eventos agregados a una página estará directamente relacionada con el rendimiento general de la página. Hay muchas razones para este problema.

En primer lugar, cada función es un objeto y ocupa memoria. Cuantos más objetos haya en la memoria, peor será el rendimiento. En segundo lugar, la cantidad de visitas DOM causadas por tener que especificar todos los controladores de eventos por adelantado retrasará el tiempo de preparación interactiva de toda la página.

La solución al problema de demasiados controladores de eventos es la delegación de eventos.

La delegación de eventos utiliza la difusión de eventos para gestionar todos los eventos de un determinado tipo especificando solo un controlador de eventos.

Por ejemplo, el evento de clic subirá al nivel del documento . Es decir, podemos especificar un controlador de eventos onclick para toda la página sin tener que agregar controladores de eventos para cada elemento en el que se puede hacer clic.

Para dar un ejemplo específico, por ejemplo, los elementos de mi lista ahora tienen el siguiente contenido:

<ul id="color-list">
  <li>red</li>
  <li>yellow</li>
  <li>blue</li>
  <li>green</li>
  <li>black</li>
  <li>white</li>
</ul>

Si queremos vincular detectores de eventos a todos los elementos li para que aparezca algo de texto cuando se hace clic en ellos, debemos vincular un detector de eventos a cada elemento.

Aunque el ejemplo anterior no parece ser un gran problema, imagine que si esta lista tiene 100 elementos, entonces necesitamos agregar 100 detectores de eventos, esta carga de trabajo sigue siendo aterradora.

En este momento podemos usar el proxy de eventos para ayudarnos a resolver este problema.

Vincula el detector de eventos al elemento principal ul para que los eventos se puedan agregar a todos los elementos li , de la siguiente manera:

var colorList = document.getElementById("color-list");
colorList.addEventListener("click",function(){
    
    
  alert("Hello");
})

Ahora, cuando hagamos clic en cualquier li de la lista , aparecerá algo emergente, como si estos elementos li fueran el objetivo del evento de clic .

Y si agregamos un nuevo elemento li a esta ul más adelante , el nuevo elemento li agregará automáticamente el mismo evento.

Sin embargo, también hay un problema en este momento: aunque usamos el proxy de eventos para evitar agregar el mismo evento para cada elemento li , si el usuario no hace clic en li pero hace clic en ul , el evento también se activará.

Esto es normal, porque nuestro evento está vinculado a ul .

En este punto, podemos hacer un pequeño juicio sobre el nodo en el que se hizo clic para asegurarnos de que el evento solo se active cuando el usuario haga clic en li , de la siguiente manera:

var colorList = document.getElementById("color-list");
colorList.addEventListener("click", function (event) {
    
    
  if (event.target.nodeName === 'LI') {
    
    
    alert('点击 li');
  }
})

Respuestas a preguntas reales

  • Hablemos de la delegación de eventos y el principio de burbujeo.

Respuesta de referencia:

La delegación de eventos también se denomina proxy de eventos. En JavaScript , la cantidad de controladores de eventos agregados a una página estará directamente relacionada con el rendimiento general de la página. Hay muchas razones para este problema.

En primer lugar, cada función es un objeto y ocupa memoria. Cuantos más objetos haya en la memoria, peor será el rendimiento. En segundo lugar, la cantidad de visitas DOM causadas por tener que especificar todos los controladores de eventos por adelantado retrasará el tiempo de preparación interactiva de toda la página.

La solución al problema de demasiados controladores de eventos es la delegación de eventos.

La delegación de eventos utiliza la difusión de eventos para gestionar todos los eventos de un determinado tipo especificando solo un controlador de eventos. Por ejemplo, el evento de clic subirá al nivel del documento . Es decir, podemos especificar un controlador de eventos onclick para toda la página sin tener que agregar controladores de eventos para cada elemento en el que se puede hacer clic.

La propagación de eventos significa que el evento es recibido inicialmente por el elemento más específico (el nodo con el nivel de anidamiento más profundo en el documento) y luego se propaga hacia arriba a nodos (documentos) menos específicos.

- EOF -

Supongo que te gusta

Origin blog.csdn.net/qq_53461589/article/details/132740098
Recomendado
Clasificación