Event Delegation در جاوا اسکریپت — از صفر تا صد
در این مقاله به بررسی یکی از مفیدترین و قدرتمندترین مفاهیم مدیریت رویداد در جاوا اسکریپت به نام «نمایندگی رویداد» (Event Delegation) میپردازیم. اما قبل از ورود به بحث باید کمی اطلاعات مقدماتی داشته باشیم.
گرفتن رویداد در جاوا اسکریپت
خصوصیت onclick به طور معمول به یک عنصر <button> در HTML الصاق میشود. این خصوصیت به دکمه امکان میدهد که یک رویداد (تابع) را در زمان کلیک شدن دکمه اجرا کند. به طور مشابه میتوانیم در یک اسکریپت یک ()addEventListener به یک دکمه اضافه کنیم. به طور کلی برای دستگیرههای رویداد onclick دو مرحله Capturing و Bubbling اتفاق میافتد.
در مرحله Capture کردن رویداد، مرورگر از بالاترین عنصر یعنی <html> بررسی میکند که آیا دستگیره onclick وجود دارد یا نه. اگر چنین باشد، پیش از آن که به سمت پایین و عنصر بعدی HTML حرکت کند، آن را اجرا میکند و این فرایند را تا زمانی که به عنصر هدف (آن که کلیک شده) برسد، ادامه میدهد.
از سوی دیگر در زمان Bubbling رویداد، مرورگر از عنصر کلیک شده (هدف) بررسی را شروع میکند و در صورتی که دستگیره onclick باشد پس از اجرا کردن به سمت بالا و عنصر بعدی HTML حرکت میکند و این فرایند را تا زمانی که به بالاترین عنصر برسد ادامه میدهد.
بصریسازی این فرایند به صورت زیر است:
نکته: در مرورگرهای مدرن به صورت پیشفرض همه دستگیرههای رویداد برای مرحله bubbling ثبت شدهاند.
به همین جهت استفاده زیاد از دستگیرههای onclick میتواند برخی اوقات به خصوص زمانهایی که یک رویداد در یک عنصر با یک عنصر والد که آن نیز دستگیره onclick دارد موجب بروز مشکل شود. چون دستگیره onclick عنصر والد حتی در صورتی که به آن نیازی نباشد هم تحریک میشود.
یک راهحل این مشکل این است که به جای آن از ()addEventListener استفاده کنیم و ()event.stopPropagation را در تابع رویداد اضافه کنیم.
با این که ممکن است به نظر برسد این دو مرحله دردسرساز هستند، اما آنها در کل بد نیستند. در واقع شما به عنوان یک توسعهدهنده میتوانید از دو مرحله Capturing و Bubbling رویداد برای پیادهسازی روشهای بهینهتر مدیریت رویداد بهره بگیرید. این مفهوم مدیریت رویداد کارآمد به نام «نمایندگی رویداد» Event Delegation شناخته میشود.
Event Delegation در جاوا اسکریپت
Event Delegation یک الگوی مدیریت رویداد قوی و کارآمد است که وقتی عناصر زیادی در یک والد رویداد یکسانی را اجرا میکنند، مورد استفاده قرار میگیرد.
به مثال زیر توجه کنید. فرض کنید یک اپلیکیشن to-do list مانند زیر داریم:
به جای افزودن یک دستگیره رویداد در هر دکمه COMPLETED برای حذف وظیفه در زمان کلیک شدن دکمه، میتوانیم یک دستگیره رویداد در عنصر والد قرار دهیم. کد HTML آن به صورت زیر است:
1<div id="task-box">
2 <h2>My Tasks</h2>
3 <div id="task">
4 <button class="done">COMPLETED</button>
5 <p>9am-10am</p>
6 <p>Walk my dog</p>
7 </div>
8 <div id="task">
9 <button class="done">COMPLETED</button>
10 <p>10am-12pm</p>
11 <p>Do homework</p>
12 </div><div id="task">
13 <button class="done">COMPLETED</button>
14 <p>12pm-4pm</p>
15 <p>Lunch with friends</p>
16 </div>
17</div>
بنابراین به جای onclick برای هر عنصر <button> یک onclick داریم که به عنصر <"div id="task-box> الصاق شده است و بررسی میکند آیا دکمه کلیک شده است یا نه و تابع ()removeTask را برای حذف این دکمه و وظیفهاش از لیست To-Do مورد استفاده قرار میدهد. کد آن به صورت زیر است:
1document.getElementById("task-box").onclick = function(event) {
2 if (event.target && event.target.matches("button.done")) {
3 removeTask(event.target.parentNode);
4 }
5});
نتیجه نهایی به صورت زیر است:
زمانی که دکمه کلیک میشود، در مرحله Bubbling بررسی میشود آیا دکمه (عنصر هدف) دارای onclick است یا نه. اگر نباشد، به سمت بالا و <"div id = “task> حرکت میکند و دوباره بررسی میکند. چون عنصر فوقانی نیز onclick ندارد، دوباره به سمت بالا و <"div id=”task-box> حرکت میکند. بالاخره یک onclick پیدا میشود. بنابراین تابع را اجرا میکند. این تابع event.target یعنی عنصر کلیک شده را بررسی میکند. اگر یک دکمه با کلاس "class = “done باشد، در این صورت <"div id = “task> را با فراخوانی تابع ()removeTask حذف میکند.
سخن پایانی
امیدواریم این مقاله کوتاه در مورد طرز کار نمایندگی رویداد (Event Delegation) و شیوه استفاده از آن در زمان Bubbling/Capturing رویداد، برای پیادهسازی مفاهیم مختلف مورد توجه شما قرار گرفته باشد.
Event Delegation در موقعیتهایی مانند لیست To-Do که عناصر به صورت مداوم حذف و اضافه میشوند بسیار مفید است، چون اضافه کردن یک onclick برای هر عنصر کار طاقتفرسایی است. با این حال کاربردهای نمایندگی رویداد به این مورد محدود نمیشود و پیادهسازی Event Delegation کاربردهای بسیار شگفتانگیزی دارد. تلاش کنید تا از این مفهوم در پروژههای خود بیشتر بهره بگیرید.
خیلی مقاله خوبی بود ممنون.