Lets say you have a parent container that also has a child element inside it.
<div class="parent">
<h1 class="child">hello</h1>
</div>
And you have added a event listener to them.
const parent = document.querySelector(".parent")
const child = document.querySelector(".child")
parent.addEventListener("click", () => {
console.log("Parent clicked!")
})
child.addEventListener("click", () => {
console.log("child clicked!")
})
Now try to click on just the parent. You should see Parent clicked!
But now if you try to click on the child element in the console you will see not only child clicked! was printed but Parent clicked! was also printed.
Why is that? That is due do something called event bubbling. So when a event is emitted on the child it will bubble up to its parent.
And it makes sense if you think about it, the child element was sitting inside its parent. So we wanted to click on just the child but in reality we clicked on both the parent and the child. So both events were fired. Now notice that first child clicked! was printed and then Parent clicked! was printed. That means the even is first fired on the child then its bubbling up to its parent. But if we want we can make it do the opposite as well.
So to do that as the third argument of our addEventListener
we can pass true
. So if we do that you will see first Parent clicked! will be printed then child clicked!.
parent.addEventListener("click", () => {
console.log("Parent clicked!")
}, true)
child.addEventListener("click", () => {
console.log("child clicked!")
}, true)
So basically passing true
as the third argument of addEventListener
tells JavaScript to use capturing mode instead of bubbling mode. And in capturing mode event is fired to the parent then goes down to its child which is the opposite of event bubbling.
Also if we want we can prevent event bubbling and event capturing by calling stopPropagation
on the event. So if we click on child only the event listener set on child will be fired and if we click on parent only the event listener set on parent will be fired.
parent.addEventListener("click", (e) => {
e.stopPropagation()
console.log("Parent clicked!")
})
child.addEventListener("click", (e) => {
e.stopPropagation()
console.log("child clicked!")
})
Alight that's all for now. Make sure you check out my other articles and YouTube Channel