Die Reise eine Events über die Elemente des DOM
Wenn ein Ereignis wie der Klick auf einen Button registriert wird, betrifft das Ereignis nicht nur den Button. Ein Klick auf einen Button triff nicht nur den Button, sondern implizit auch ein »darunter liegendes« Element wie ein div, unter dem das body-Element liegt und unter dem wiederum das documentElement und am Ende das Window sitzt.
Ein Äquivalent dazu: Wenn ich auf den Teppich trete, trete ich auch auf den Holzboden darunter, unter dem wiederum der Estrich ist.
<body> <main> <button id=button>Klick mich</button> </main> … </body>
Events reisen vom Root zum Element
Aus der Sicht des DOM reist ein Ereignis in der Capture-Phase vom ROOT des Dokuments zu seinem Ziel und benachrichtigt auf dem Weg nach unten jedes Element. Liegt für die betroffenen Elemente auf dem Weg zum getriggerten Element kein eventListener an, überhören die Elemente das Event.
Ein Event beginnt nicht auf dem getriggerten Element,
sondern am ROOT,
und reist im DOM-Baum nach unten.
Wenn es die Art des Ereignisses erlaubt, steigt das Ereignis in einer Bubbling-Phase durch den Baum zurück nach oben und könnte in der Bubbling-Phase ebenfalls jedes Element auf dem Weg nach oben triggern.
capture -----┐ │ ▼ button.addEventListener ("click", alertMe, true); button.addEventListener ("click", alertMe, false); ▲ │ bubble ----┘
Der dritte Parameter von addEventListener – useCapture – legt fest, in welcher Phase ein Event einen Event Listener aktiviert.
- Capture
- true Zuerst die Event Handler von Vorfahren aufrufen, dann erst den Event Handler des Elements
- Bubble
- false (default) Zuerst den Event Handler des Elements aufrufen, erst dann die Event Handler von Vorfahren
Bubbling Phase
Wenn ein Skript Ereignisse auf verschachtelten HTML-/XML-Elementen registriert, die auf dasselbe Ereigniss warten, führt der Browser beim Bubbling die innerste Registrierung zuerst aus und arbeitet sich dann nach oben vor.
<div class="root"> <div class="middle"> <div class="inner"> <button class="btn">inneres Element</button> </div> </div> </div>
Event delegation ist eine elegante Methode und macht sich das Event Bubbling zunutze: Statt einen EventListener auf jedes Element zu setzen, bindet Event Delegation den Event Listener an das Parent Element.
Capturing Phase
Beim Capturing {useCapture: true} behandelt der Browser das Ereignis auf dem Weg »nach unten«. Das oberste Element mit einem eventListener meldet das das Event zuerst. Wenn das Event bei seinem Ziel, dem target, angekommen ist, reist das Event in der bubble-Phase zurück zum Element nach oben.
Wir ziehen heute fast immer bubble (false) vor.
Für moderne Skripte macht es selten Sinn, ein Event von mehreren Event Handlern behandeln zu lassen. Wenn wir auf ein Element klicken, erwarten wir eine Aktion auf diesem Element. Darum wird jedes Event in einem eigenen Skript behandelt.
Also können wir den dritten Parameter meist fallen lassen – bubble (false) ist der Default-Wert – und der dritte Parameter ist optional.
Nach oben
Wenn der Event Listener jedoch auch auf den Elementen über dem getriggerten Element liegt – so z.B. auf den Elemente dieser verschachtelten HTML-Liste –, ist capture angebracht, um das Ereignis an der korrekten Stelle zu empfangen.
bubble false
- Element 1
- Element 2
- Element 3
- Element 4
- Element 5
- Element 6
- Element 7
- Element 8
- Element 9
- Element 10
bubble true – capture
- Element 1
- Element 2
- Element 3
- Element 4
- Element 5
- Element 6
- Element 7
- Element 8
- Element 9
- Element 10
Bubble: Bei einem Klick auf einen Text der ersten Liste reagiert das Parent-Element,
Capture: Bei einem Klick auf ein Element der zweiten Liste nur das Element selber. Darum zeigt die dunkle Konsole über der Liste bei einem Klick auf Element 9 den Text Element 5, ein Klick auf die bubble:true-Liste den Text Element 9.