Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Event Bubbling vs Event Capturing in JavaScript

2025年09月14日に「Dev.to」が公開したITニュース「Event Bubbling vs Event Capturing in JavaScript」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

JavaScriptのイベントは、クリックした要素だけでなくDOMツリーを伝わる。この伝播には、親から子へ向かう「キャプチャリング」と、子から親へ向かう「バブリング」の2種類がある。JavaScriptのデフォルトはバブリングだが、addEventListenerでキャプチャリングも指定できる。

ITニュース解説

Webページを操作する際、例えばボタンをクリックしたり、テキストフィールドに文字を入力したりすると、JavaScriptはその操作を「イベント」として認識し、それに応じた処理を実行する。しかし、HTML要素が互いに入れ子になっている(ネストされている)場合、ユーザーがクリックした要素だけでイベントが終わるわけではない。イベントはHTMLの構造、つまりDOM(Document Object Model)ツリーの中を移動する特性を持っている。このイベントの移動方法には「イベントキャプチャリング」と「イベントバブリング」という二つの主要な流れがある。

まず、イベントキャプチャリングについて説明する。これは、イベントがHTMLの最上位要素であるdocumentから始まり、クリックされた目的の要素(ターゲット要素)に向かって、DOMツリーを上から下へと伝播していくフェーズを指す。例えば、HTMLのbodyタグの中にdivタグがあり、さらにその中にbuttonタグがあると仮定する。ユーザーがこのbuttonをクリックした場合、イベントはまずdocumentで発生したと認識され、次にbody、その次にdivへと順に伝わり、最終的にbuttonに到達する。この段階で、各親要素はイベントを「捕獲(キャプチャ)」する機会を得る。つまり、ターゲット要素にイベントが到達する前に、途中の親要素がイベントを傍受して何らかの処理を行うことができる。

次に、イベントバブリングについて説明する。これは、イベントキャプチャリングとは逆に、ターゲット要素でイベントが発生した後、そのイベントがDOMツリーを「下から上へ」と伝播していくフェーズを指す。先ほどの例で言えば、buttonがクリックされると、まずbutton自身でイベントが発生する。その後、イベントはbuttonの親要素であるdiv、さらにその親であるbody、そして最上位のdocumentへと順に「泡が上昇するように」伝わっていく。このフェーズでも、イベントが通過する各親要素は、そのイベントを検知し、対応する処理を実行する機会を得る。

JavaScriptにおいて、イベントリスナーを設定するためのaddEventListenerメソッドは、デフォルトでイベントバブリングを利用する。つまり、何も指定しなければ、イベントはターゲット要素から親要素へと伝播していく途中で処理される。しかし、addEventListenerメソッドの第三引数にtrueを渡すことで、イベントキャプチャリングのフェーズでイベントを処理するように設定できる。例えば、あるbutton要素へのクリックイベントを処理する場合、単にbutton.addEventListener("click", () => { console.log("Button clicked!"); });と記述すると、イベントはバブリングフェーズで処理される。一方で、div要素に対してdiv.addEventListener("click", () => { console.log("DIV clicked during capturing!"); }, true);と記述すると、divはクリックイベントがターゲット要素(この場合はbutton)に到達する前のキャプチャリングフェーズでイベントを検知し、処理を実行する。

ユーザーがネストされた要素をクリックした際、実際にイベントがどのように流れるかというイベントフローの順序は、この二つのフェーズが組み合わさって成り立っている。具体的には、以下の三段階で進行する。 第一段階は「キャプチャリングフェーズ」である。イベントはdocumentからターゲット要素に向かって上から下へと伝播する。 第二段階は「ターゲットフェーズ」である。イベントが実際にクリックされたターゲット要素自身で発生する。 第三段階は「バブリングフェーズ」である。イベントはターゲット要素からdocumentに向かって下から上へと伝播する。 したがって、buttonがクリックされた場合、イベントフローはdocumentbodydivbutton(キャプチャリング)、button(ターゲット)、buttondivbodydocument(バブリング)という順序で進むことになる。

これらのイベントフローの仕組みを理解することは、堅牢で効率的なWebアプリケーションを開発する上で非常に重要である。イベントキャプチャリングは比較的珍しいケースで利用されるが、イベントがターゲットに到達する前に処理をインターセプト(傍受)したい場合に役立つ。例えば、特定の条件下で子要素へのイベントを完全にブロックしたい場合などに利用できる。一方、イベントバブリングは非常に一般的であり、特に「イベント委譲(Event Delegation)」という強力なパターンでその真価を発揮する。イベント委譲とは、多数の子要素それぞれに個別のイベントリスナーを設定する代わりに、それらの子要素をまとめる一つの親要素にイベントリスナーを設定する手法である。親要素に一つだけリスナーを設定しておけば、子要素で発生したイベントがバブリングによって親要素まで伝播してきたときに、そのイベントを捕らえて処理できる。これにより、メモリの使用量を抑え、動的に追加・削除される子要素に対しても自動的にイベントハンドリングを適用できるという大きなメリットがある。

このように、JavaScriptにおけるイベント伝播のメカニズムであるイベントキャプチャリングとイベントバブリングは、単なる概念ではなく、Webアプリケーションの挙動を深く理解し、より柔軟で高性能なコードを書くための基盤となる知識である。これらの二つのフェーズがどのように機能し、どのように制御できるかを把握することで、イベントハンドリングの可能性を最大限に引き出すことができる。

関連コンテンツ