First implement a small function: after clicking the HTML button, output the message to the console.
In order to implement this small function, you need to select the button, and then use the addEventListener()
method to attach an event listener:
<button id="buttonId">Click me</button> <script> document.getElementById('buttonId') .addEventListener('click', () => console.log('Clicked!')); </script>
The above is to listen to a single element ( Especially the way events are done on buttons).
What if you need to listen to events on multiple buttons? Here's a possible implementation:
<div id="buttons"> <button class="buttonClass">Click me</button> <button class="buttonClass">Click me</button> <!-- buttons... --> <button class="buttonClass">Click me</button> </div> <script> const buttons = document.getElementsByClassName('buttonClass'); for (const button of buttons) { button.addEventListener('click', () => console.log('Clicked!')); } </script>
You can see how it works on Codesandbox.
The button list is iterated as for (const button of buttons)
and a new listener is attached to each button. In addition, after buttons are added or removed from the list, you must also manually remove or attach event listeners.
Is there a better way?
Fortunately, if we use the "event delegation" pattern, listening to events on multiple elements only requires one event listener.
Details of the event propagation mechanism used by event delegation. To understand how event delegation works, you should first understand what event propagation is.
When you click the button in the html below:
<html> <body> <div id="buttons"> <button class="buttonClass">Click me</button> </div> </body> </html>
How many elements will the click event fire? No doubt the button itself receives the click event. And all button ancestors, even document
and window
objects will also be received.
The propagation of click events is divided into three stages:
Capture stage —— From window
, document
Starting with the root element, the event propagates down to the ancestors of the target element
Target phase - The event is triggered on the element clicked by the user
Bubbling Phase - Finally, the event bubbles through the ancestors of the target element, all the way to the root elements document
and window
.
addEventListener
The third parameter of the methodcaptureOrOptions
:
element.addEventListener(eventType, handler[, captureOrOptions]);
enables you to capture events from different stages.
captureOrOptions
parameter is missing or is false
or {capture:false}
##Events of target and bubble phases or
{capture: true}, then detect The listener will listen for
capture phase events. element:
document.body.addEventListener('click', () => { console.log('Body click event in capture phase'); }, true);
, you can see how the event propagates in the console when you click the button. So how does event propagation help capture multiple button events?
The algorithm is simple: Attach an event listener to the button's parent and capture the bubbling event when the button is clicked. This is how event delegation works.
3. Event Delegate
<div id="buttons"> <!-- Step 1 --> <button class="buttonClass">Click me</button> <button class="buttonClass">Click me</button> <!-- buttons... --> <button class="buttonClass">Click me</button> </div> <script> document.getElementById('buttons') .addEventListener('click', event => { // Step 2 if (event.target.className === 'buttonClass') { // Step 3 console.log('Click!'); } }); </script>
Open the
Codesandbox demo and click Any button, you will see 'Click!' message is logged to the console. The idea of event delegation is very simple. You don't need to attach the delegate event listener directly to the button. Instead, you can delegate the parent listener
The above is the detailed content of An in-depth analysis of event delegation in JS. For more information, please follow other related articles on the PHP Chinese website!