Was ist das Sprudeln und Erfassen von Ereignissen?

Antworten:

1439

Das Sprudeln und Erfassen von Ereignissen sind zwei Möglichkeiten der Ereignisweitergabe in der HTML-DOM-API, wenn ein Ereignis in einem Element in einem anderen Element auftritt und beide Elemente ein Handle für dieses Ereignis registriert haben. Der Ereignisausbreitungsmodus bestimmt, in welcher Reihenfolge die Elemente das Ereignis empfangen .

Beim Sprudeln wird das Ereignis zuerst vom innersten Element erfasst und verarbeitet und dann an die äußeren Elemente weitergegeben.

Bei der Erfassung wird das Ereignis zuerst vom äußersten Element erfasst und an die inneren Elemente weitergegeben.

Das Erfassen wird auch als "Rinnsal" bezeichnet, wodurch die Ausbreitungsreihenfolge gespeichert wird:

rieseln, sprudeln

Früher befürwortete Netscape die Erfassung von Ereignissen, während Microsoft das Sprudeln von Ereignissen förderte. Beide sind Teil des W3C- Standards für Dokumentobjektmodellereignisse (2000).

IE <9 verwendet nur Ereignisblasen , während IE9 + und alle gängigen Browser beide unterstützen. Andererseits kann die Leistung des Ereignisblasens bei komplexen DOMs geringfügig geringer sein.

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

Beispiel

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

Nehmen Sie in der obigen Struktur an, dass im liElement ein Klickereignis aufgetreten ist.

Beim Erfassen des Modells wird das Ereignis zuerst behandelt div(klicken Sie auf Ereignishandler im divTestament wird zuerst ausgelöst ), dann im ul, dann zuletzt im Zielelement li.

Im Bubbling-Modell geschieht das Gegenteil: Das Ereignis wird zuerst vom li, dann vom ulund schließlich vom divElement behandelt.

Weitere Informationen finden Sie unter

Wenn Sie im folgenden Beispiel auf eines der hervorgehobenen Elemente klicken, sehen Sie, dass die Erfassungsphase des Ereignisausbreitungsflusses zuerst erfolgt, gefolgt von der Blasenphase.

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());
}

function clearOutput() {
    logElement.innerHTML = "";
}

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);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
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 id="clear">clear output</button>
<section id="log"></section>

Ein weiteres Beispiel bei JSFiddle .

Arun P Johny
quelle
41
useCapturejetzt unterstützt in IE> = 9. Quelle
Beatgammit
7
Ich weiß, es ist zu spät, um einen Kommentar abzugeben,
Nur Code
3
Ist triclklingdas gleiche wie capturing? Crockford spricht über Trickling v. Bubblingin diesem Video talk - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB um 1 hr 5 minutes.
Kevin Meredith
1
@ KevinMeredith Das Gleiche. „Rieseln“ einfach macht es einfacher , sich daran zu erinnern , was die beiden Modelle haben (trickle nach unten , Blase oben ).
eine Katze
7
Die obige Antwort ist in Bezug auf die Reihenfolge in der detaillierten Erklärung korrekt, lässt Sie jedoch denken, dass das Rinnsal an zweiter Stelle mit "Blase hoch, Rinnsal runter" auftritt. Ereignisse durchlaufen immer die Erfassungsphase vor der Blasenphase. Die richtige Reihenfolge ist trickle down=> onElement=>bubble up
Runspired
513

Beschreibung:

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

Ereigniserfassung

Wenn Sie die 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 ist zu verwenden?

Es hängt davon ab, was Sie tun möchten. Besser geht es nicht. Der Unterschied ist die Reihenfolge der Ausführung der Ereignishandler. In den meisten Fällen ist es in Ordnung, Ereignishandler in der Blasenphase zu feuern , es kann jedoch auch erforderlich sein, sie früher zu feuern.

Felix Kling
quelle
Passiert nicht beides, erst erfassen und dann sprudeln, auch was ist ein Versandereignis?
Suraj Jain
Ein grafisches Beispiel finden Sie hier: javascript.info/bubbling-and-capturing
Community Ans
71

Wenn es zwei Elemente gibt, Element 1 und Element 2. Element 2 befindet sich innerhalb von Element 1 und wir fügen einen Ereignishandler mit beiden Elementen hinzu, sagen wir onClick. Wenn wir nun auf Element 2 klicken, wird eventHandler für beide Elemente ausgeführt. Hier stellt sich nun 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 mit Element 2 verknüpfte Ereignis zuerst ausgeführt wird, wird dies als Ereignisblasenbildung bezeichnet. Gemäß W3C beginnt das Ereignis in der Erfassungsphase, bis es das Ziel erreicht, zum Element zurückkehrt und dann zu sprudeln beginnt

Die Erfassungs- und Blasenzustände sind dem Parameter useCapture der Methode addEventListener bekannt

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

Standardmäßig ist useCapture falsch. Es bedeutet, dass es sich in der Blasenphase befindet.

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.

dinesh_malhotra
quelle
2
@masterxilo: Fiddle wird nicht benötigt, StackOverflow unterstützt jetzt Inline-Code (Stack-Snippets) .
Dan Dascalescu
In Bezug auf the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling. Ich habe nur festgestellt, dass der addEventListener den Parameter hat, der useCaptureauf true oder false gesetzt werden kann. und in HTML 4.0, Event - Listener wurden als Attribute eines Elements angegeben und useCapture defaults to false. Könnten Sie auf eine Spezifikation verweisen, die bestätigt, was Sie geschrieben haben?
Surfmuggle
25

Ich habe festgestellt, dass dieses Tutorial unter javascript.info sehr klar ist, um dieses Thema zu erklären. Und die 3-Punkte-Zusammenfassung am Ende spricht wirklich die entscheidenden Punkte an. Ich zitiere es hier:

  1. Ereignisse werden zuerst bis zum tiefsten Ziel erfasst und dann in die Luft gesprudelt. In IE <9 sprudeln sie nur.
  2. Alle Handler arbeiten mit Ausnahme des addEventListenerletzten Arguments an sprudelnden Bühnenausnahmen. Dies trueist die einzige Möglichkeit, das Ereignis auf der Erfassungsbühne zu erfassen.
  3. Bubbling / Capturing kann von event.cancelBubble=true(IE) oder event.stopPropagation() für andere Browser gestoppt werden.
gm2008
quelle
7

Es gibt auch die Event.eventPhaseEigenschaft, die Ihnen sagen kann, ob das Ereignis am Ziel ist oder von einem anderen Ort kommt.

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

Wenn Sie das bereits große Snippet aus der akzeptierten Antwort erweitern , ist dies die Ausgabe, die die eventPhaseEigenschaft verwendet

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>

Adelin
quelle
5

Sprudeln

  Event propagate to the upto root element is **BUBBLING**.

Erfassen

  Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.
Kondal
quelle