رهام رفیعی تهرانی
رهام رفیعی تهرانی
خواندن ۴ دقیقه·۱ سال پیش

تفاوت stopPropagation و stopImmediatePropagation


یکی از مهمترین قسمت های اپلیکیشن های وب، مدیریت event هاست . مثلا وقتی event کلیک روی یک element اتفاق می افته چه مراحلی طی میشه؟

وقتی کلیک روی یک element اتفاق می افته، سه فاز طی میشه:

  1. فاز capture
  2. فاز target
  3. فاز bubble


در فاز اول ( capture phase ) رویداد click از ریشه DOM Tree ( مثلا document ) این قدر پایین میره تا به target element برسه. وقتی به target element رسید وارد فاز دوم یعنی target phase میشه . بعد وارد فاز سوم به اسم bubble phase میشه و از target element به سمت ریشه DOM Tree حرکت میکنه.

با مرور یک مثال این فازها رو بررسی کنیم:

در کد بالا وقتی روی button کلیک میکنیم چه اتفاقی می افته؟

اول وارد فاز capture phase میشیم:

  1. آیا دایکومنت میخواد callback برای کلیک رجیستر کنه؟ به صورت پیش فرض جوابش خیره.
  2. آیا html میخواد callback برای کلیک رجیستر کنه؟ به صورت پیش فرض جوابش خیره.
  3. آیا body میخواد callback برای کلیک رجیستر کنه؟ به صورت پیش فرض جوابش خیره.
  4. آیا div میخواد callback برای کلیک رجیستر کنه؟ به صورت پیش فرض جوابش خیره.


رسیدیم به target element که همون button هست. آیا button برای کلیک calback event داره؟ اگر بله که رجیستر میشه


حالا میریم سراغ فاز bubble phase:

  1. آیا div تابع callback برای کلیک داره؟ اگر داره رجیستر میشه ...
  2. آیا body تابع callback برای کلیک داره؟ اگر داره رجیستر میشه...
  3. آیا html تابع callback برای کلیک داره؟ اگر داره رجیستر میشه...
  4. آیا document تابع callback برای کلیک داره؟ اگر داره رجیستر میشه...


همه callback هایی که رجیستر شدند، به ترتیب اجرا میشن.



یه نکته ریزی داره این داستان. ترتیب این event ها رو میشه تغییر داد؟

جوابش اینه که : بله. میشه تغییرش داد!!

چطوری؟

تابع addEventListener یک ورودی سومی داره بنام options که میشه بهش مقدار boolean داد. مقدار پیش فرضش false هست. اگر مقدار true بهش بدیم چه چیزی تغییر میکنه؟

تابع callback مدنظر ما بجای اینکه در bubble phase رجیستر بشه، در capture phase رجیستر میشه. در مثال قبلی، اگر فقط addEventListener رو برای body ، با پارامتر سوم true رجیستر کنیم، callback المنت body زودتر از button و div رجیستر و اجرا میشه. درحالیکه به طور طبیعی باید callback های اونها زودتر صدا زده بشه.

یعنی وقتی روی button کلیک میکنیم:

  • اول تابع callback المنت body صدا زده میشه که از capture phase رجیستر شده
  • بعد تابع callback المنت button صدا زده میشه که از target phase رجیستر شده.
  • بعد تابع callback المنت div صدا زده میشه که از bubble phase رجیستر شده.



حالا فرق stopPropagation و stopImmidiatePropagation چیه؟

کد زیر رو در نظر بگیرید:

این کد میگه روی click event المنت body دو تابع رجیستر کردیم. در تابع اول stopPropagation رو صدا زدیم و در تابع دوم یک console.log داریم. نکته مهم اینه که هر دو تابع رو برای یک المنت و داخل یک فاز ( capture phase یا bubble phase فرقی نمیکنه ) رجیستر کردیم.

فرض کنید روی دکمه button در مثال بالا کلیک کنیم. چون گفتیم هر دو تابع callback برای یک المنت و در یک فاز رجیستر بشوند، صدا کردن تابع stopPropagation در تابع اول مانع از اجرای تابع callback دوم ( که مربوط به همون المنت و در همون فاز هست ) نمیشه. و ما شاهد خروجی 2nd event handler called! خواهیم بود. و بقیه callback ها صدا زده نمیشن. در حالیکه اگر از stopImmediatePropagation استفاده کنیم، نه تابع callback دوم صدا زده میشه نه بقیه callback ها.


اطلاعاتی مفیدی که میتونید از event دریافت کنید

متغیر 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 استفاده کنید. وگرنه ممکنه مجبور بشین کلی وقت بگذارین و مشکل کدتون رو پیدا کنین.


موفق باشید :)


event handlerdom eventsjavascriptجاوااسکریپتhtml
برنامه نویسی یک شغل نیست، یک هنره.
شاید از این پست‌ها خوشتان بیاید