當你點擊一個元素,事件不是只在那個元素上觸發。它從樹的頂端往下傳到目標(capture 階段),在目標本身觸發(target 階段),再往上傳回頂端(bubble 階段)。預設你加的監聽器在 bubble 階段執行,這就是為什麼點子元素也會觸發祖先的 handler。用 capture 模式加監聽器,則會改在下行途中執行。
在監聽器裡呼叫 stopPropagation,會讓事件不再往下一層傳遞,剩下的層就不會被觸發。它不會擋掉同一元素上的其他監聽器——那是 stopImmediatePropagation 的工作。在上方選一個中斷點,看觸發順序被截短。
關於這個主題的常見疑問與實用解答。
它們是同一趟旅程的兩個方向。capture 由上而下,從最外層祖先往目標走,發生在抵達目標之前。bubble 由下而上,從目標往最外層祖先走。用一般方式加的監聽器在 bubble 階段執行;給 addEventListener 第三個參數傳 true,就改在 capture 階段執行。
因為冒泡。事件在子元素(目標)上觸發後,會往上傳回每一層祖先,沿路執行各層的 bubble 階段監聽器。這常常有用——讓容器上的一個 handler 就能回應任何子元素的點擊——但會讓以為事件只停在被點元素上的人意外。
少用為妙,只在子元素要處理事件、且真的必須阻止祖先也反應時用——例如可點擊卡片裡的一顆按鈕,不該同時觸發卡片的點擊。太常用它通常代表事件設計可以更簡單;它也可能弄壞其他正當依賴事件傳到共同祖先的程式。