Czym jest zjawisko bulgotania i przechwytywania?

Jaka jest różnica między bulgotaniem zdarzeń a przechwytywaniem? Z tych dwóch, który model jest szybszy i lepszy w użyciu?

Author: bjb568, 2011-01-06

5 answers

Event bubbling i przechwytywanie są dwoma sposobami propagacji zdarzeń w HTML DOM API, gdy zdarzenie występuje w elemencie wewnątrz innego elementu, a oba elementy zarejestrowały uchwyt dla tego zdarzenia. Tryb propagacji zdarzeń określa w , w jakiej kolejności elementy otrzymują Zdarzenie.

W przypadku bubblingu, zdarzenie jest najpierw przechwytywane i obsługiwane przez najbardziej Wewnętrzny element, a następnie propagowane do elementów zewnętrznych.

Z przechwytywaniem, zdarzenie jest najpierw przechwytywane przez element zewnętrzny i propagowane do elementów wewnętrznych.

Przechwytywanie jest również nazywane "ściekaniem" , co pomaga zapamiętać kolejność propagacji:]}

Spływaj w dół, bańka w górę

W dawnych czasach Netscape zalecał przechwytywanie zdarzeń, podczas gdy Microsoft promował event bubbling. Oba są częścią Standardu W3C Document Object Model Events standard (2000).

IE tylko event bubbling, podczas gdy IE9+ i wszystkie główne przeglądarki wspieraj oba. Z drugiej strony, wydajność bąbelkowania zdarzeń może być nieco niższa dla złożonych domów.

Możemy użyć addEventListener(type, listener, useCapture) do rejestracji procesów obsługi zdarzeń w trybie bubbling (domyślnym) lub capture. Aby użyć modelu przechwytywania, podaj trzeci argument jako true.

Przykład

<div>
    <ul>
        <li></li>
    </ul>
</div>

W powyższej strukturze Załóżmy, że w elemencie li wystąpiło zdarzenie kliknięcia.

W modelu przechwytywania, zdarzenie będzie obsługiwane przez div najpierw (kliknij Narzędzia obsługi zdarzeń w div uruchomi się najpierw), następnie w ul, a na końcu w elemencie docelowym, li.

W modelu bubbling dzieje się odwrotnie: zdarzenie będzie najpierw obsługiwane przez li, Następnie przez ul, a na końcu przez div element.

Aby uzyskać więcej informacji, zobacz

W poniższym przykładzie, jeśli klikniesz na któryś z wyróżnionych elementów, zobaczysz, że najpierw następuje faza przechwytywania przepływu propagacji zdarzenia, a następnie faza bąbelkowa.

var logElement = document.getElementById('log');

function log(msg) {
    logElement.innerHTML += ('<p>' + msg + '</p>');
}

function capture() {
    log('capture: ' + this.firstChild.nodeValue.trim());
}

function bubble() {
    log('bubble: ' + this.firstChild.nodeValue.trim());
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', capture, true);
    divs[i].addEventListener('click', bubble, false);
}
p {
    line-height: 0;
}

div {
    display:inline-block;
    padding: 5px;

    background: #fff;
    border: 1px solid #aaa;
    cursor: pointer;
}

div:hover {
    border: 1px solid #faa;
    background: #fdd;
}
<div>1
    <div>2
        <div>3
            <div>4
                <div>5</div>
            </div>
        </div>
    </div>
</div>
<section id="log"></section>

Kolejny przykład w JSFiddle .

 1180
Author: Arun P Johny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 16:07:33

Opis:

quirksmode.org ma ładny opis tego. W skrócie (skopiowane z quirksmode):

Przechwytywanie zdarzeń

Gdy używasz przechwytywania zdarzeń

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

Obsługa zdarzeń element1 zostanie wywołana jako pierwsza, obsługa zdarzeń element2 zostanie wywołana jako ostatnia.

Event bubbling

Kiedy używasz event bubbling

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

Obsługa zdarzenia element2 zostanie wywołana jako pierwsza, Obsługa zdarzenia element1 zostanie wywołana jako ostatnia.


Czego użyć?

To zależy od tego, co chcesz zrobić. Nie ma lepszego. Różnica polega na kolejności wykonania procedur obsługi zdarzeń. Przez większość czasu można odpalić procedury obsługi zdarzeń w fazie bubbling, ale może być również konieczne wcześniejsze odpalenie ich.
 460
Author: Felix Kling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-06 15:46:18

Jeśli istnieją dwa elementy element 1 i element 2. Element 2 jest wewnątrz elementu 1 i dołączamy obsługę zdarzeń z obu elementów powiedzmy onClick. Teraz, gdy klikniemy na element 2, eventHandler dla obu elementów zostanie wykonany. Teraz pytanie brzmi, w jakiej kolejności zdarzenie zostanie wykonane. Jeśli zdarzenie dołączone do elementu 1 zostanie wywołane jako pierwsze, nazywa się to przechwytywaniem zdarzeń, a jeśli zdarzenie dołączone do elementu 2 zostanie wywołane jako pierwsze, nazywa się to bulgotaniem zdarzeń. Zgodnie z W3C Zdarzenie rozpocznie się w fazie przechwytywania, dopóki nie dotrze do celu, wróci do elementu, a następnie zacznie bulgotać

Stany przechwytywania i bąbelkowania są znane za pomocą parametru useCapture metody addEventListener

EventTarget.addEventListener(type, listener, [, useCapture]);

Domyślnie useCapture jest false. To znaczy, że jest w fazie bulgotania.

var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");

div1.addEventListener("click", function (event) {
  alert("you clicked on div 1");
}, true);

div2.addEventListener("click", function (event) {
  alert("you clicked on div 2");
}, false);
#div1{
  background-color:red;
  padding: 24px;
}

#div2{
  background-color:green;
}
<div id="div1">
  div 1
  <div id="div2">
    div 2
  </div>
</div>

Proszę spróbować zmienić true I false.

 64
Author: dinesh_malhotra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-25 22:16:47

Znalazłem ten tutorial na javascript.info aby być bardzo jasne w wyjaśnieniu tego tematu. A jego 3-punktowe podsumowanie na końcu naprawdę mówi o kluczowych punktach. Cytuję tutaj:

  1. zdarzenia najpierw są rejestrowane w dół do najgłębszego celu, a następnie bańki w górę. W IE
  2. wszyscy handlerzy pracują na scenie z wyjątkiem addEventListener z ostatnim argumentem true, który jest jedynym sposobem na Złap wydarzenie na scenie przechwytywania.
  3. Bubbling / przechwytywanie może być zatrzymany przez zdarzenie.cancelBubble = true (IE) lub event.stopropagacja() dla innych przeglądarek.
 23
Author: gm2008,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-14 08:51:09

Jest też Event.eventPhase właściwość, która może Ci powiedzieć, czy zdarzenie jest w punkcie docelowym lub pochodzi z innego miejsca.

Należy pamiętać, że kompatybilność przeglądarki nie jest jeszcze ustalona. Testowałem go na Chrome (66.0.3359.181) i Firefox (59.0.3) i jest tam obsługiwany.

Rozszerzając na już Wielki fragment z zaakceptowanej odpowiedzi , jest to wyjście przy użyciu właściwości eventPhase

var logElement = document.getElementById('log');

function log(msg) {
  if (logElement.innerHTML == "<p>No logs</p>")
    logElement.innerHTML = "";
  logElement.innerHTML += ('<p>' + msg + '</p>');
}

function humanizeEvent(eventPhase){
  switch(eventPhase){
    case 1: //Event.CAPTURING_PHASE
      return "Event is being propagated through the target's ancestor objects";
    case 2: //Event.AT_TARGET
      return "The event has arrived at the event's target";
    case 3: //Event.BUBBLING_PHASE
      return "The event is propagating back up through the target's ancestors in reverse order";
  }
}
function capture(e) {
  log('capture: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

function bubble(e) {
  log('bubble: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', capture, true);
  divs[i].addEventListener('click', bubble, false);
}
p {
  line-height: 0;
}

div {
  display:inline-block;
  padding: 5px;

  background: #fff;
  border: 1px solid #aaa;
  cursor: pointer;
}

div:hover {
  border: 1px solid #faa;
  background: #fdd;
}
<div>1
  <div>2
    <div>3
      <div>4
        <div>5</div>
      </div>
    </div>
  </div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>
 1
Author: Adelin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-29 12:54:00