要素をクリックすると、イベントはその要素だけで発火するわけではありません。ツリーの最上部から始まり、ターゲットまで下っていき(capture フェーズ)、ターゲット自身で発火し(target フェーズ)、また最上部へ戻ります(bubble フェーズ)。既定では追加したリスナーは bubble フェーズで実行されます。だから子要素のクリックが祖先のハンドラーも起動します。capture モードでリスナーを追加すると、下る途中で実行されます。
リスナー内で stopPropagation を呼ぶと、イベントはそれ以上伝わらなくなり、残りの層のリスナーは実行されません。同じ要素上の他のリスナーは止めません。それは stopImmediatePropagation の役目です。上で停止地点を選ぶと、発火順序が途中で切れるのを確認できます。
このテーマに関するよくある疑問と回答をまとめました。
同じ旅の2つの方向です。capture は上から下へ、最も外側の祖先からターゲットへ、ターゲットに到達する前に進みます。bubble は下から上へ、ターゲットから最も外側の祖先へ進みます。通常の方法で追加したリスナーは bubble フェーズで実行され、addEventListener の第3引数に true を渡すと capture フェーズで実行されます。
バブリングのためです。イベントが子要素(ターゲット)で発火した後、すべての祖先へ上っていき、その途中で各層の bubble フェーズのリスナーを実行します。これは便利なことが多く、コンテナ上の1つのハンドラーで任意の子のクリックに応答できます。しかし、イベントがクリックした要素に留まると思っている人を驚かせます。
控えめに使いましょう。子要素がイベントを処理し、祖先も反応するのを本当に防ぐ必要があるときだけです。たとえばクリック可能なカード内のボタンが、カードのクリックを起動すべきでない場合です。多用しすぎるのは、たいていイベント設計をもっと単純にできる兆候です。共有の祖先にイベントが届くことに正当に依存している他のコードを壊すこともあります。