28- آموزش جاوااسکریپت | درک حبابسازی رویداد (Event Bubbling) و واگذاری رویداد (Event Delegation)
در این آموزش، دو مفهوم کلیدی و پیشرفته در مدیریت رویدادهای DOM، یعنی «حبابسازی رویداد» (Event Bubbling) و «واگذاری رویداد» (Event Delegation) را بررسی میکنیم. یاد میگیرید که چگونه رویدادها در ساختار درختی DOM به سمت والدین حرکت میکنند
در این بخش، به بررسی دو مفهوم بسیار مهم در جاوااسکریپت میپردازیم که درک آنها برای مدیریت حرفهای DOM ضروری است.
حبابسازی رویداد (Event Bubbling)
حبابسازی رویداد به این معناست که وقتی رویدادی روی یک عنصر رخ میدهد، آن رویداد به سمت بالا در ساختار درختی DOM «حباب» کرده و به ترتیب به عناصر والد (Parent) منتقل میشود. به عبارت دیگر، اگر روی یک دکمه کلیک کنید، آن کلیک ابتدا برای خود دکمه، سپس والد آن، و سپس والدِ والد آن رخ میدهد. (رویداد از هدف به سمت والدها بالا میرود)
مثال: اگر روی card-title کلیک کنید، تمام والدین آن (مانند card-content و card) نیز رویداد کلیک را دریافت میکنند، حتی اگر ما مستقیماً روی آنها کلیک نکرده باشیم.
// فعال شدن رویدادها به دلیل حبابسازی (Bubbling)
document.querySelector('.card-title').addEventListener('click', function() {
console.log('Card Title clicked');
});
document.querySelector('.card-content').addEventListener('click', function() {
console.log('Card Content clicked');
});
واگذاری رویداد (Event Delegation)
واگذاری رویداد (Delegation) تقریباً برعکسِ حبابسازی است؛ اما از همان مکانیسم استفاده میکند. در اینجا به جای اینکه به تکتک عناصر (مثلاً ۱۰۰ آیتم لیست) یک EventListener بدهیم، رویداد را روی یک عنصر والد (Parent) قرار میدهیم. سپس با استفاده از منطق شرطی در تابع، تشخیص میدهیم که آیا کلیک روی عنصر هدف ما بوده است یا خیر. (سپردن مدیریت رویدادِ فرزندان به والد)
چرا از Delegation استفاده میکنیم؟ ۱. بهینهسازی حافظه: به جای افزودن تعداد زیادی Listener، فقط یک Listener روی والد داریم. ۲. عناصر داینامیک: اگر با جاوااسکریپت عنصری جدید به لیست اضافه کنید، رویدادهای معمولی روی آن کار نمیکنند، اما Delegation چون روی والد است، همیشه کار میکند.
مثال کاربردی (حذف آیتمهای لیست):
// اضافه کردن رویداد به والد به جای تکتک آیتمها
document.body.addEventListener('click', function(e) {
// بررسی اینکه آیا عنصر کلیک شده دارای کلاس 'delete-item' است
if (e.target.parentElement.classList.contains('delete-item')) {
// حذف کل آیتم لیست (Parentِ Parent)
e.target.parentElement.parentElement.remove();
console.log('Delete item');
}
});
نکات کلیدی در این کد:
e.target: عنصری را که کاربر روی آن کلیک کرده برمیگرداند.- بررسی کلاس با
classList.contains: این روش مطمئنتر ازclassNameاست، زیرا حتی اگر عناصر کلاسهای دیگری هم داشته باشند، کد ما به درستی کار میکند. parentElement: چون ممکن است کاربر روی آیکونِ حذف (<i>) کلیک کند نه خودِ لینک (<a>)، با استفاده از پیمایشِ والد (Parent)، به کلاس اصلی میرسیم.
در آموزشهای آینده، از این مفاهیم برای ساخت یک پروژه کامل (To-Do List) استفاده خواهیم کرد که در آن عملیات اضافه کردن و حذف کردن آیتمها به صورت داینامیک انجام میشود.