Frage Was sprudelt und fängt das Ereignis ein?


Was ist der Unterschied zwischen Event-Blubbern und Capturen? Von den beiden, welches ist das schnellere und bessere Modell zu benutzen?


826
2018-01-06 15:44


Ursprung


Antworten:


Event Bubbling und Capturing sind zwei Arten der Ereignisausbreitung in der HTML DOM API, wenn ein Ereignis in einem Element innerhalb eines anderen Elements auftritt und beide Elemente einen Handle für dieses Ereignis registriert haben. Der Ereignisausbreitungsmodus bestimmt in In welcher Reihenfolge erhalten die Elemente das Ereignis.

Beim Bubbling wird das Ereignis zuerst vom innersten Element erfasst und gehandhabt und dann zu äußeren Elementen propagiert.

Beim Capturing wird das Ereignis zuerst vom äußersten Element erfasst und an die inneren Elemente weitergegeben.

Capturing wird auch "trickling" genannt, was hilft, sich an die Ausbreitungsreihenfolge zu erinnern:

rieseln, sprudeln

In den alten Zeiten befürwortete Netscape das Ereignis-Capturing, während Microsoft das Bubbling von Ereignissen förderte. Beide sind Teil des W3C Document Object Model Ereignisse Standard (2000).

IE <9 verwendet nur sprudelndes Ereignis, während IE9 + und alle gängigen Browser beide unterstützen. Auf der anderen Seite, die Die Leistung der Ereignisblasenbildung kann geringfügig niedriger sein für komplexe DOMs.

Wir können das benutzen addEventListener(type, listener, useCapture) um Event-Handler entweder im Bubbling- (Standard) oder Capturing-Modus zu registrieren. Um das Erfassungsmodell zu verwenden, übergeben Sie das dritte Argument als true.

Beispiel

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

Gehen Sie in der obigen Struktur davon aus, dass ein Klickereignis in der li Element.

Beim Erfassen des Modells wird die Veranstaltung von der div zuerst (klicken Sie auf Ereignishandler in der div wird zuerst schießen), dann in der ul, dann am letzten im Zielelement, li.

Im sprudelnden Modell wird das Gegenteil passieren: Die Veranstaltung wird zuerst von der lidann durch die ulund zuletzt durch die div Element.

Weitere Informationen finden Sie unter

Wenn Sie im folgenden Beispiel auf eines der markierten Elemente klicken, können Sie sehen, dass zuerst die Erfassungsphase des Ereignisausbreitungsflusses und dann die Bubbling-Phase erfolgt.

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>

Ein anderes Beispiel bei JSFiddle.


1146
2018-01-06 15:47



Beschreibung:

quirksmode.org hat eine schöne Beschreibung davon. Kurz gesagt (kopiert von quirksmode):

Ereigniserfassung

Wenn Sie Ereigniserfassung verwenden

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

Der Ereignishandler von element1 wird zuerst ausgelöst, der Ereignishandler von element2 wird zuletzt ausgelöst.

Ereignis sprudelt

Wenn Sie Ereignisblasen verwenden

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

Der Ereignishandler von element2 wird zuerst ausgelöst, der Ereignishandler von element1 wird zuletzt ausgelöst.


Was zu verwenden?

Es hängt davon ab, was Sie tun möchten. Es gibt kein besseres. Der Unterschied ist die Reihenfolge der Ausführung der Event-Handler. Die meiste Zeit ist es in Ordnung, Ereignishandler in der brodelt Phase, aber es kann auch notwendig sein, sie früher zu feuern.


455
2018-01-06 15:46



Wenn es zwei Elemente gibt, Element 1 und Element 2. Element 2 ist innerhalb von Element 1 und wir fügen einen Event-Handler mit beiden Elementen an, sagen wir onClick. Wenn wir nun auf Element 2 klicken, wird eventHandler für beide Elemente ausgeführt. Jetzt ist hier die Frage, in welcher Reihenfolge das Ereignis ausgeführt wird. Wenn das mit Element 1 verknüpfte Ereignis zuerst ausgeführt wird, wird es als Ereigniserfassung bezeichnet, und wenn das Ereignis, das mit Element 2 verknüpft ist, zuerst ausgeführt wird, wird dies Ereignis-Bubbling genannt. Gemäß W3C beginnt das Ereignis in der Erfassungsphase, bis es das Ziel erreicht, kommt zurück zum Element und dann beginnt es zu sprudeln

Die erfassenden und sprudelnden Zustände sind dem useCapture-Parameter der addEventListener-Methode bekannt

eventTarget.addEventListener (Typ, Listener, [, useCapture]);

Standardmäßig ist useCapture false. Es bedeutet, dass es in der sprudelnden Phase ist.

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>

Bitte versuchen Sie es mit wahr und falsch zu ändern.


63
2018-03-04 12:45



Ich habe das gefunden Anleitung bei javascript.info um dieses Thema sehr klar zu erklären. Und seine 3-Punkte-Zusammenfassung am Ende spricht wirklich zu den entscheidenden Punkten. Ich zitiere es hier:

  1. Ereignisse werden zuerst bis zum tiefsten Ziel erfasst und dann aufsteigen. Im   IE <9 sie sprudeln nur.
  2. Alle Handler arbeiten an sprudelnden Bühnenausnahmen   addEventListener mit dem letzten Argument true, was der einzige Weg ist   Fang das Event auf der Bühne.
  3. Sprudeln / Einfangen kann sein   gestoppt von event.cancelBubble = true (IE) oder event.stopPropagation ()   für andere Browser.

23
2018-05-14 08:51



Es gibt auch die Event.eventPhase Eigenschaft, die Ihnen sagen kann, ob das Ereignis am Ziel ist oder von woanders kommt.

Beachten Sie, dass die Browserkompatibilität noch nicht festgelegt ist. Ich habe es in Chrome (66.0.3359.181) und Firefox (59.0.3) getestet und es wird dort unterstützt.

Erweiterung auf die bereits großer Ausschnitt aus der angenommenen Antwort, das ist die Ausgabe mit der eventPhase Eigentum

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>


0
2018-05-29 07:31