Event Capturing و Event Bubbling در جاوااسکریپت

داستان از اونجا شروع شد که میخواستم یه Modal بنویسم و میخواستم زمانی که این Modal باز بود یه پس زمینه تیره داشته باشیم و اگر روی باکس Modal کلیک شد بتونم روی دکمه OK کلیک کنم و اگر روی پس زمینه تیره کلیک کردم این Modal بسته بشه به همین سادگی :)

modal
modal


در جاوا اسکریپت یه مفهومی به اسم Event Flow وجود داره که ترتیب کلیک شدن روی المنت هارو مدیریت میکنه و دو حالت Event Capturing و Event Bubbling داره در حالت پیش فرض روی Event Bubbling قرار داره و به این صورته که از داخلی ترین فرزند، Event شروع به انتشار میکنه و تا بالا ترین والد ادامه پیدا میکنه

مثلا فرض کنید قطعه کد زیر رو داریم:

<div id=&quotmodalWrapper&quot>
    <button id=&quotmodal&quot>click me</button>
</div>
let parent = document.querySelector('#modalWrapper');
parent.addEventListener('click', ()=>{
    console.log(&quotParent clicked&quot);
});
let child = document.querySelector('#modal');
child.addEventListener('click', ()=>{
    console.log(&quotChild clicked&quot);
});


در این کد به ترتیب المنت های زیر رو داریم

button , div , body , html , document , window

و با کلیک روی click me به ترتیب از داخلی ترین فرزند یعنی button ایونت ها صدا زده میشن و خروجی این کد میشه

// Child clicked

// Parent clicked


و اگر بخوایم این ترتیب رو برعکس کنیم باید از آرگومان سوم addEventListener که مقدار boolean میگیره که خیلی ها از جمله خود من تا چند وقت پیش کاربردشو نمیدونستم استفاده کنیم :)

این مقدار به صورت پیشفرض برابر با false هستش و اگر این مقدار رو برابر true قرار بدیم ترتیب صدا شدن ایونت ها برعکس میشه و از خارجی ترین والد به سمت داخلی ترین فرزند حرکت میکنه

<div id=&quotmodalWrapper&quot>
    <button id=&quotmodal&quot>click me</button>
</div>
let parent = document.querySelector('#modalWrapper');
parent.addEventListener('click', ()=>{
    console.log(&quotParent clicked&quot);
},true);
let child = document.querySelector('#modal');
child.addEventListener('click', ()=>{
    console.log(&quotChild clicked&quot);
},true);


در نتیجه به ترتیب المنت های زیر رو داریم

window , document , html , body , div , button

و با کلیک روی click me به ترتیب از خارجی ترین والد ایونت ها صدا زده میشن و خروجی این کد میشه

// Parent clicked

// Child clicked


Event Capturing VS Event Bubbling
Event Capturing VS Event Bubbling



و همچنین اگر بخوایم با صدا شدن یک Event فرایند انتشار سایر Event ها متوقف بشه میتونیم از stopPropagation استفاده کنیم که روش استفاده از این متد به صورت زیر می باشد .


<div id=&quotmodalWrapper&quot>
    <button id=&quotmodal&quot>click me</button>
</div>
let parent = document.querySelector('#modalWrapper');
parent.addEventListener('click', (e)=>{
    console.log(&quotParent clicked&quot);
});
let child = document.querySelector('#modal');
child.addEventListener('click', (e)=>{
    console.log(&quotChild clicked&quot);
e.stopPropagation();
});


و نتیجه کد بالا برابر است با

// Child clicked

ممنون که وقت گذاشتی، لطفا هر موردی که از قلم انداختم کامنت کن که به این مقاله اضافه کنم ;)