Event Propagation in JavaScript
Event Bubbling, Event Capturing, Event Delegation

UI Engineer @Flipkart I like to explore new technologies & build projects on them.
Search for a command to run...
Event Bubbling, Event Capturing, Event Delegation

UI Engineer @Flipkart I like to explore new technologies & build projects on them.
No comments yet. Be the first to comment.
Let's enable infinite scroll for virtual scrollbars

Introduction Javascript is a single-threaded interpreted language with a non-blocking event loop. What this means is that everything runs on a single main thread so it's important to use the thread only when required. Blocking this main thread means ...

Introduction One of the reasons React is so popular is that it's blazing fast. This speed is achieved by updating only part of the real DOM that has changed. But, updating the real DOM is a slow process. So, how does React achieve this? React achieve...

An event travels or propagates through the DOM tree, this is called Event propagation.
This can happen in 2 ways -
<div id="grand-parent">
<div id="parent">
<div id="target">
</div>
</div>
</div>
grandParent.addEventListener("click",() => console.log("Grand Parent"))
parent.addEventListener("click",() => console.log("Parent"))
target.addEventListener("click",() => console.log("Target"))
-Now click on the target div (smallest one)
Remember event bubbling as bubbles coming up to the top surface of a water
Now, we want to reverse the order of events. But how do we do that? There's a third parameter taken by the addEventListner which accepts a boolean value, which is false by default. This attribute tells the handler if the event is to be captured or not.
If the third parameter is set to true the event capturing mode is enabled.
grandParent.addEventListener("click",()=>console.log("Grand Parent"),true)
parent.addEventListener("click",()=>console.log("Parent"),true)
target.addEventListener("click",()=>console.log("Target"),true)
-Now click on the target div (smallest one)
Remember event capturing/trickling as water trickling down the slope of a mountain
Consider the code below where only the parent event has capture set to true
grandParent.addEventListener("click",() => console.log("Grand Parent"))
parent.addEventListener("click",() => console.log("Parent"),true)
target.addEventListener("click",() => console.log("Target"))
What would be the logged on the console on clicking the target(smallest) div now?
on clicking the target div(smallest div) :
In an event propagation cycle, the capturing phase occurs first then followed by the target phase and bubbling phase.
Consider the image below -

So far we saw an event propagating either up or down the DOM tree but what if we only want the event to happen on the target div and do not propagate, say we want to log on which div the user clicked, here we could use something as: e.stopPropagation()
grandParent.addEventListener("click",() => console.log("Grand Parent"))
parent.addEventListener("click",() => console.log("Parent"))
target.addEventListener(
"click",
(e) => {
e.stopPropagation();
console.log("Target");
}
)
Try clicking on target(smallest) div :
Here, since the target has a stopPropagation so events from the target won't propagate. i.e. on clicking on target(smallest) div we will see only target in the console.
Try clicking on the parent div now- Since there is no such stopPropagation on the parent, clicking on the parent will still behave as it behaved before and consoled parent => grandparent
Event delegation is a performance optimization technique. Say you have a shopping site where there are multiple categories, now if you attach onClick handlers to each category then when the page is fully loaded then it will have too many event listeners. Having too many event listeners can slow down the performance of a web app and hence event delegation comes to the rescue.
Instead of attaching event listeners to all target elements, attach an event listener to the parent and with the help of the event-bubbling get what target has been clicked.
const parent = document.querySelector("#parent");
parent.addEventListener("click",(e) => console.log(e.target.innerText))
Click on the numbered divs it will console the number of the div clicked
Event Bubbling - start from the target element and traverse up in the DOM tree Event Capturing - start from the top of the DOM tree and traverse down to the target Event Delegation - Instead of attaching multiple events listeners attach one event listener to the parent and with the help of event bubbling get on which element the event has occurred.