Nie można zrozumieć parametru useCapture w addeventlistener

Przeczytałem artykuł na https://developer.mozilla.org/en/DOM/element.addEventListener ale nie mogę zrozumieć useCapture atrybutu. Definicja istnieje:

Jeśli to prawda, useCapture wskazuje, że użytkownik chce rozpocząć przechwytywanie. Po zainicjowaniu przechwytywania wszystkie zdarzenia określonego typu zostaną wysłane do zarejestrowanego detektora przed wysłaniem do dowolnego EventTargets znajdującego się pod nim w drzewie DOM. Wydarzenia, które bulgoczą w górę przez drzewo, nie będą Uruchom słuchacza wyznaczonego do użycia przechwytywania.

W tym kodzie rodzic wywołuje zdarzenie przed dzieckiem,więc nie jestem w stanie zrozumieć jego zachowanie.Obiekt Document ma wartość usecapture true, obiekt potomny div ma wartość usecapture ustawioną false, a document usecapture jest followed.So dlaczego właściwość document jest preferowana w stosunku do właściwości potomnych.

function load() {
  document.addEventListener("click", function() {
    alert("parent event");
  }, true);

  document.getElementById("div1").addEventListener("click", function() {
    alert("child event");
  }, false);
}
<body onload="load()">
  <div id="div1">click me</div>
</body>
Author: vsync, 2011-09-13

9 answers

Zdarzenia mogą być aktywowane dwa razy: na początku ("przechwytywanie") i na końcu ("bańka"). Zdarzenia są wykonywane w kolejności ich zdefiniowania. Powiedzmy, że zdefiniujesz 4 słuchaczy zdarzeń:

window.addEventListener("click", function(){alert(1)}, false);
window.addEventListener("click", function(){alert(2)}, true);
window.addEventListener("click", function(){alert(3)}, false);
window.addEventListener("click", function(){alert(4)}, true);

Pola alarmowe pojawią się w tej kolejności:

  • 2 (zdefiniowany jako pierwszy, używając capture=true)
  • 4 (zdefiniowano drugi za pomocą capture=true)
  • 1 (pierwsze zdefiniowane Zdarzenie z capture=false)
  • 3 (drugie zdefiniowane Zdarzenie z capture=false)
 302
Author: Rob W,
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-11-19 20:18:23

Uważam, że ten diagram jest bardzo przydatny do zrozumienia fazy przechwytywania / celu/bańki: http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

Poniżej treść wyciągnięta z linku.

Fazy

Zdarzenie jest wysyłane po ścieżce od korzenia drzewa do tego węzła docelowego. Następnie może być obsługiwany lokalnie na poziomie węzła docelowego lub z przodków dowolnego celu wyżej w drzewie. Dyspozytornia wydarzenia (zwana także propagacją zdarzeń) występuje w trzech fazach i następującej kolejności:

  1. Faza przechwytywania: zdarzenie jest wysyłane do przodków celu od korzenia drzewa do bezpośredniego rodzica węzła docelowego.
  2. Faza docelowa: zdarzenie jest wysyłane do węzła docelowego.
  3. Faza bąbelkowa: zdarzenie jest wysyłane do celu przodków od bezpośredniego rodzica węzła docelowego do korzenia drzewo.

graficzna reprezentacja zdarzenia wysyłanego w drzewie DOM przy użyciu przepływu zdarzeń DOM

The przodkowie celu są ustalani przed pierwszym wysłaniem zdarzenia. Jeśli węzeł docelowy zostanie usunięty podczas wysyłania, lub jego przodek zostanie dodany lub usunięty, propagacja zdarzenia zawsze będzie oparta na węźle docelowym i przodkach celu określonych przed wysyłką.

Niektóre zdarzenia niekoniecznie muszą spełniać trzy fazy przepływu zdarzeń DOM, np. zdarzenie może być zdefiniowane tylko dla jednej lub dwóch faz. Jako przykład, zdarzenia zdefiniowane w tym Specyfikacja zawsze osiągnie fazę przechwytywania i celowania, ale niektóre nie osiągną fazy bąbelkowej ("bąbelkowe zdarzenia" versus "nie bąbelkowe zdarzenia", patrz także Zdarzenie.atrybut bubbles).

 219
Author: lax4mike,
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
2014-11-25 16:42:12

Capture Event vs Bubble Event

  • Zdarzenie przechwytywania zostanie wysłane przed wydarzeniem Bubble
  • kolejność propagacji zdarzeń jest
    1. Wychwytywanie Rodzica
    2. Wychwytywanie Dzieci
    3. Bańka Dla Dzieci
    4. Bańka Rodzica

( stopPropagation() zatrzyma przepływ)

                  |  A
 -----------------|--|-----------------
 | Parent         |  |                |
 |   -------------|--|-----------     |
 |   |Children    V  |          |     |
 |   ----------------------------     |
 |                                    |
 --------------------------------------

Demo

var parent = document.getElementById('parent'),
    child  = document.getElementById('child');

child.addEventListener('click', function(e){ 
    console.log('Child Capture, with capture');
    // e.stopPropagation();
}, true);

child.addEventListener('click', function(e){ 
    console.log('Child Bubble');
    // e.stopPropagation();
}, false);

parent.addEventListener('click', function(e){ 
    console.log('Parent Capture, with capture');
    // e.stopPropagation();
}, true);

parent.addEventListener('click', function(e){ 
    console.log('Parent Bubble');
    // e.stopPropagation();
}, false);
<div id="parent">
    <button id="child">Click</button>
</div>
 57
Author: Steely Wing,
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-11-19 20:14:57

Kiedy mówisz useCapture = true zdarzenia wykonują od góry do dołu w fazie przechwytywania, gdy false robi bańkę od dołu do góry.

 14
Author: sushil bharwani,
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-09-13 07:57:07

Przykład kodu:

<div id="div1" style="background:#9595FF">
  Outer Div<br />
  <div id="div2" style="background:#FFFFFF">
    Inner Div
  </div>
</div>

Kod Javascript:

d1 = document.getElementById("div1");
d2 = document.getElementById("div2");

Jeśli oba są ustawione na false

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},false);

Wykonuje: Onclicking Inner Div, alerty wyświetlane są jako: Div 2 > Div 1

Tutaj skrypt jest wykonywany z elementu wewnętrznego: Event Bubbling (useCapture został ustawiony na false)

Div 1 jest ustawiony na true, a div 2 Na false

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},false);

Wykonuje: Onclicking Inner Div, alerty wyświetlane są jako: Div 1 > Div 2

Tutaj skrypt jest wykonywany z element nadrzędny / zewnętrzny: przechwytywanie zdarzeń (useCapture został ustawiony na true)

Div 1 jest ustawione na false, a div 2 na true

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},true);

Wykonuje: Onclicking Inner Div, alerty wyświetlane są jako: Div 2 > Div 1

Tutaj skrypt jest wykonywany z elementu wewnętrznego: Event Bubbling (useCapture został ustawiony na false)

Div 1 jest ustawiony na true, a div 2 na true

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},true);

Wykonuje: Onclicking Inner Div, alerty wyświetlane są jako: Div 1 > Div 2

Tutaj skrypt jest wykonywany z elementu nadrzędnego / zewnętrznego: przechwytywanie zdarzeń, ponieważ useCapture został ustawiony na true

 11
Author: shadowBot,
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
2014-08-06 00:09:13

Wszystko o modelach zdarzeń: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow Możesz przechwycić Zdarzenie w fazie bulgotania lub w fazie przechwytywania. Twój wybór.
Spójrz na http://www.quirksmode.org/js/events_order.html - uznasz to za bardzo przydatne.

 10
Author: NilColor,
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
2012-10-05 17:43:29

Biorąc pod uwagę trzy fazy zdarzenia podróż :

  1. Faza Przechwytywania : zdarzenie jest wysyłane do przodków celu od korzenia drzewa do bezpośredniego rodzica celu węzeł.
  2. Faza docelowa : zdarzenie jest wysyłane do węzła docelowego.
  3. the bubbling phase : zdarzenie jest wysyłane do przodków celu od bezpośredniego rodzica węzła docelowego do korzenia drzewo.

useCapture wskazuje, w jakich fazach będzie przebiegać wydarzenietravel:

Jeśli true, useCapture wskazuje, że użytkownik chce dodać zdarzenie słuchacza tylko w fazie przechwytywania, tzn. ten słuchacz zdarzenia nie będzie być wyzwalane podczas fazy celu i bulgotania. If false, the detektor zdarzeń zostanie uruchomiony tylko podczas target i bulgotania fazy

Źródło jest takie samo jak druga najlepsza odpowiedź: https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

 6
Author: Aurimas,
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-03-12 07:08:30

Podsumowanie:

Spec opisany w:

Https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

Działa w następujący sposób:

Zdarzenie jest wysyłane po ścieżce od korzenia (document) drzewa do węzła docelowego . Węzeł docelowy jest najgłębszym elementem HTML, tzn. zdarzeniem.cel. Wysyłanie zdarzeń (zwane także propagacją zdarzeń) odbywa się w trzech fazach i następujących kolejność:

  1. Faza przechwytywania: zdarzenie jest wysyłane do przodków celu z korzenia drzewa (document) do bezpośredniego rodzica węzła docelowego.
  2. Faza docelowa: zdarzenie jest wysyłane do węzła docelowego. Faza docelowa jest zawsze na najgłębszym elemencie html, na którym zdarzenie zostało rozproszone.
  3. Faza bąbelkowa: zdarzenie jest wysyłane do przodków celu z bezpośredniego rodzica węzła docelowego do korzeń drzewa.

Event bubbling, event capture, event target

Przykład:

// bubbling handlers, third argument (useCapture) false (default)
document.getElementById('outerBubble').addEventListener('click', () => {
  console.log('outerBubble');
}, false)

document.getElementById('innerBubble').addEventListener('click', () => {
  console.log('innerBubble');
}, false)


// capturing handlers, third argument (useCapture)  true
document.getElementById('outerCapture').addEventListener('click', () => {
  console.log('outerCapture');
}, true)

document.getElementById('innerCapture').addEventListener('click', () => {
  console.log('innerCapture');
}, true)
div:hover{
  color: red;
  cursor: pointer;
}
<!-- event bubbling -->
<div id="outerBubble">
  <div id="innerBubble">click me to see Bubbling</div>
</div>


<!-- event capturing -->
<div id="outerCapture">
  <div id="innerCapture">click me to see Capturing</div>
</div>

Powyższy przykład naprawdę ilustruje różnicę między bulgotaniem zdarzeń a przechwytywaniem zdarzeń. Podczas dodawania detektorów zdarzeń z addEventListener, istnieje trzeci element o nazwie useCapture. To a boolean, które po ustawieniu na true pozwala słuchaczowi zdarzeń używać przechwytywania zdarzeń zamiast bulgotania zdarzeń.

W naszym przykładzie, gdy ustawimy useCapture argument do false widzimy, że zdarzenie ma miejsce. Najpierw zostanie wywołane zdarzenie w fazie docelowej( logs innerBubble), a następnie poprzez event bubbling zostanie wywołane zdarzenie w elemencie nadrzędnym (logs outerBubble).

Kiedy ustawimy argument useCapture na true widzimy, że zdarzenie zewnętrzne <div> jest wywołane jako pierwsze. Dzieje się tak dlatego, że zdarzenie jest teraz wywoływane w fazie przechwytywania, a nie w fazie bąbelkowej.

 2
Author: Willem van der Veen,
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-08-25 14:26:05

Kolejność definicji ma znaczenie tylko wtedy, gdy pozycje są na tym samym poziomie. Jeśli odwrócisz kolejność definicji w kodzie, otrzymasz takie same wyniki.

Jednakże, jeśli odwrócisz ustawienie useCapture w dwóch procedurach obsługi zdarzeń, to proces obsługi zdarzeń potomnych odpowie przed procesem rodzicielskim. Powodem tego jest to, że podrzędna obsługa zdarzeń zostanie uruchomiona w fazie przechwytywania, która jest poprzedzona fazą bulgotania, w której zostanie uruchomiona rodzicielska obsługa zdarzeń.

Jeśli ustawisz useCapture na true dla obu programów obsługi zdarzeń-niezależnie od kolejności definicji-to program obsługi zdarzeń rodzica zostanie uruchomiony jako pierwszy, ponieważ jest on poprzedzony programem potomnym w fazie przechwytywania.

Odwrotnie, jeśli ustawisz useCapture na false dla obu programów obsługi zdarzeń-ponownie niezależnie od kolejności definicji-program obsługi zdarzeń potomnych zostanie uruchomiony jako pierwszy, ponieważ jest przed rodzicem w fazie bulgotania.

 1
Author: WXB13,
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
2013-01-25 03:53:40