Was ist der Unterschied zwischen Ereignisblasen und Erfassen? Wann sollte man Bubbling vs Capturing verwenden?
Was ist der Unterschied zwischen Ereignisblasen und Erfassen? Wann sollte man Bubbling vs Capturing verwenden?
Antworten:
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
.
<div>
<ul>
<li></li>
</ul>
</div>
Nehmen Sie in der obigen Struktur an, dass im li
Element ein Klickereignis aufgetreten ist.
Beim Erfassen des Modells wird das Ereignis zuerst behandelt div
(klicken Sie auf Ereignishandler im div
Testament 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 ul
und schließlich vom div
Element 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>
useCapture
jetzt unterstützt in IE> = 9. Quelle
triclkling
das gleiche wie capturing
? Crockford spricht über Trickling v. Bubbling
in diesem Video talk - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB um 1 hr 5 minutes
.
trickle down
=> onElement
=>bubble up
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.
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.
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 useCapture
auf 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?
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:
- Ereignisse werden zuerst bis zum tiefsten Ziel erfasst und dann in die Luft gesprudelt. In IE <9 sprudeln sie nur.
- Alle Handler arbeiten mit Ausnahme des
addEventListener
letzten Arguments an sprudelnden Bühnenausnahmen. Diestrue
ist die einzige Möglichkeit, das Ereignis auf der Erfassungsbühne zu erfassen.- Bubbling / Capturing kann von
event.cancelBubble=true
(IE) oderevent.stopPropagation()
für andere Browser gestoppt werden.
Es gibt auch die Event.eventPhase
Eigenschaft, 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 eventPhase
Eigenschaft 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>