یکی از مهمترین قسمت های اپلیکیشن های وب، مدیریت event هاست . مثلا وقتی event کلیک روی یک element اتفاق می افته چه مراحلی طی میشه؟
وقتی کلیک روی یک element اتفاق می افته، سه فاز طی میشه:
در فاز اول ( capture phase ) رویداد click از ریشه DOM Tree ( مثلا document ) این قدر پایین میره تا به target element برسه. وقتی به target element رسید وارد فاز دوم یعنی target phase میشه . بعد وارد فاز سوم به اسم bubble phase میشه و از target element به سمت ریشه DOM Tree حرکت میکنه.
با مرور یک مثال این فازها رو بررسی کنیم:
در کد بالا وقتی روی button کلیک میکنیم چه اتفاقی می افته؟
اول وارد فاز capture phase میشیم:
رسیدیم به target element که همون button هست. آیا button برای کلیک calback event داره؟ اگر بله که رجیستر میشه
حالا میریم سراغ فاز bubble phase:
همه callback هایی که رجیستر شدند، به ترتیب اجرا میشن.
یه نکته ریزی داره این داستان. ترتیب این event ها رو میشه تغییر داد؟
جوابش اینه که : بله. میشه تغییرش داد!!
چطوری؟
تابع addEventListener یک ورودی سومی داره بنام options که میشه بهش مقدار boolean داد. مقدار پیش فرضش false هست. اگر مقدار true بهش بدیم چه چیزی تغییر میکنه؟
تابع callback مدنظر ما بجای اینکه در bubble phase رجیستر بشه، در capture phase رجیستر میشه. در مثال قبلی، اگر فقط addEventListener رو برای body ، با پارامتر سوم true رجیستر کنیم، callback المنت body زودتر از button و div رجیستر و اجرا میشه. درحالیکه به طور طبیعی باید callback های اونها زودتر صدا زده بشه.
یعنی وقتی روی button کلیک میکنیم:
کد زیر رو در نظر بگیرید:
این کد میگه روی click event المنت body دو تابع رجیستر کردیم. در تابع اول stopPropagation رو صدا زدیم و در تابع دوم یک console.log داریم. نکته مهم اینه که هر دو تابع رو برای یک المنت و داخل یک فاز ( capture phase یا bubble phase فرقی نمیکنه ) رجیستر کردیم.
فرض کنید روی دکمه button در مثال بالا کلیک کنیم. چون گفتیم هر دو تابع callback برای یک المنت و در یک فاز رجیستر بشوند، صدا کردن تابع stopPropagation در تابع اول مانع از اجرای تابع callback دوم ( که مربوط به همون المنت و در همون فاز هست ) نمیشه. و ما شاهد خروجی 2nd event handler called! خواهیم بود. و بقیه callback ها صدا زده نمیشن. در حالیکه اگر از stopImmediatePropagation استفاده کنیم، نه تابع callback دوم صدا زده میشه نه بقیه callback ها.
متغیر event که به callback ارسال شده، اطلاعاتی رو در مورد اینکه event در کدوم فاز اجرا میشه و غیره به ما برمیگردونه که اینجا خلاصه ش میکنیم:
event.eventPhase
مشخصه read-only هست که مشخص میکنه event flow در کدوم فاز هست و به این callback رسیده.
مقدارش با یکی از مقادیر زیر برابره:
event.CAPTURING_PHASE (1)
event.AT_TARGET (2)
event.BUBBLING_PHASE (3)
به مثال زیر توجه کنید:
از مقدار event.currentTarget هم میشه به اون المنتی رسید که event براش اتفاق افتاده.
در این مقاله روند اجرای callback رو در DOM Element ها مرور کردیم و با سه فازش آشنا شدیم. بعدش تفاوت stopPropagation و stopImmediatePropagation رو مرور کردیم.
اگر میخواید مطمئن باشید که هیچ callback event دیگه ای بعد از callback شما صدا زده نمیشه، حتما از stopImmediateProparation استفاده کنید. وگرنه ممکنه مجبور بشین کلی وقت بگذارین و مشکل کدتون رو پیدا کنین.
موفق باشید :)