イベントバブリングとキャプチャリングを使い分けるポイント

2024-04-02

イベントバブリングとキャプチャリングとは?

イベントバブリングは、イベントが発生した要素から、その要素の親要素、さらにその親要素へと、DOMツリーを遡っていくようにイベントハンドラが呼び出される仕組みです。

例えば、以下のようなHTMLコードがあるとします。

<div id="outer">
  <div id="inner">
    <button id="button">ボタン</button>
  </div>
</div>

button要素をクリックすると、以下の順番でイベントハンドラが呼び出されます。

  1. button要素
  2. inner要素
  3. outer要素

これは、イベントが最初にbutton要素で発生し、その後、inner要素、outer要素へと伝播していくためです。

イベントキャプチャリングは、イベントバブリングとは逆方向に、DOMツリーを下っていくようにイベントハンドラが呼び出される仕組みです。

イベントキャプチャリングを使用するには、イベントリスナーの第3引数をtrueに設定する必要があります。

上記の例で、inner要素のイベントリスナーの第3引数をtrueに設定すると、以下の順番でイベントハンドラが呼び出されます。

イベントバブリングとキャプチャリングは、それぞれ異なる目的で使用されます。

イベントバブリング

  • 多くの場合、イベントバブリングを使用します。
  • イベントが発生した要素を特定する必要がない場合に便利です。
  • 例えば、ページ全体のどこをクリックしても、同じ処理を実行したい場合などです。

イベントバブリングとキャプチャリングは、JavaScriptにおけるDOMイベント処理の重要な概念です。イベントが発生したとき、どのようにイベントハンドラが呼び出されるかを理解することで、より効率的なコードを書くことができます。




イベントバブリングとキャプチャリングのサンプルコード

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>イベントバブリングとキャプチャリング</title>
</head>
<body>
  <div id="outer">
    <div id="inner">
      <button id="button">ボタン</button>
    </div>
  </div>
  <script>
  // イベントバブリング

  // outer要素のイベントハンドラ
  document.getElementById("outer").addEventListener("click", function() {
    console.log("outer要素がクリックされました");
  });

  // inner要素のイベントハンドラ
  document.getElementById("inner").addEventListener("click", function() {
    console.log("inner要素がクリックされました");
  });

  // button要素のイベントハンドラ
  document.getElementById("button").addEventListener("click", function() {
    console.log("button要素がクリックされました");
  });

  // イベントキャプチャリング

  // outer要素のイベントハンドラ
  document.getElementById("outer").addEventListener("click", function(event) {
    console.log("outer要素がクリックされました (キャプチャリング)");
  }, true);

  // inner要素のイベントハンドラ
  document.getElementById("inner").addEventListener("click", function(event) {
    console.log("inner要素がクリックされました (キャプチャリング)");
  }, true);

  // button要素のイベントハンドラ
  document.getElementById("button").addEventListener("click", function(event) {
    console.log("button要素がクリックされました (キャプチャリング)");
  }, true);
  </script>
</body>
</html>

このコードを実行すると、以下の結果が出力されます。

button要素がクリックされました
inner要素がクリックされました
outer要素がクリックされました
outer要素がクリックされました (キャプチャリング)
inner要素がクリックされました (キャプチャリング)
button要素がクリックされました (キャプチャリング)

outer要素、inner要素、button要素それぞれに、clickイベントのイベントハンドラが設定されています。

イベントハンドラの第3引数をtrueに設定することで、イベントキャプチャリングを使用しています。




イベントバブリングとキャプチャリングの代替方法

イベント委譲は、イベントバブリングを利用して、親要素でイベント処理を行う手法です。イベントが発生した要素を特定する必要がなく、コードを簡潔に記述できます。

以下のコードは、イベント委譲を使用して、button要素がクリックされたときに処理を実行する例です。

<div id="outer">
  <div id="inner">
    <button id="button">ボタン</button>
  </div>
</div>
// outer要素のイベントハンドラ
document.getElementById("outer").addEventListener("click", function(event) {
  // イベントが発生した要素がbutton要素であれば処理を実行
  if (event.target.id === "button") {
    console.log("button要素がクリックされました");
  }
});

イベントリスナーを直接要素に設定することで、イベントバブリングやキャプチャリングに関係なく、イベント処理を行うことができます。

以下のコードは、button要素に直接イベントリスナーを設定して、クリックされたときに処理を実行する例です。

<div id="outer">
  <div id="inner">
    <button id="button">ボタン</button>
  </div>
</div>
// button要素のイベントハンドラ
document.getElementById("button").addEventListener("click", function() {
  console.log("button要素がクリックされました");
});

イベントの停止

イベント伝播を途中で止めることで、バブリングやキャプチャリングによる不要な処理を防ぐことができます。

以下のコードは、button要素がクリックされたときに、イベント伝播を停止する例です。

<div id="outer">
  <div id="inner">
    <button id="button">ボタン</button>
  </div>
</div>
// button要素のイベントハンドラ
document.getElementById("button").addEventListener("click", function(event) {
  console.log("button要素がクリックされました");

  // イベント伝播を停止
  event.stopPropagation();
});

イベントバブリングとキャプチャリングは、イベント処理の基本的な手法ですが、状況によっては代替方法が必要になる場合があります。イベント委譲、イベントリスナーの直接設定、イベントの停止などの方法を理解することで、より柔軟なイベント処理を行うことができます。


javascript dom-events event-bubbling


Trelloでクリップボードを賢く使って、ワークフローを加速させる

navigator. clipboard API概要:2018年に導入された比較的新しいAPIです。ユーザーの同意なしにクリップボードにアクセスすることはできません。ユーザーがアクセスを許可した場合、Trelloはクリップボードの内容を読み取り、書き込むことができます。...


React コンポーネント間通信:Redux と MobX で大規模アプリケーションを制覇

概要親コンポーネントから子コンポーネントへデータを渡す最も基本的な方法です。props は、子コンポーネントに渡されるオブジェクトで、コンポーネントの属性として指定されます。メリットシンプルで分かりやすい軽量で効率的一方向にしかデータを渡せない...


TypeScript で ES6 Map を使いこなす

Map の利点:キーと値のペアを保存するのに最適な方法です。他のデータ構造 (オブジェクトなど) よりも高速で効率的です。さまざまな種類のデータ (オブジェクト、配列、文字列など) を保存できます。繰り返し処理や検索が簡単です。TypeScript で Map を使用するには、Map 型を使用します。...


JavaScript、jQuery、Moment.jsで「認識されないISO形式」を解決

Moment. jsライブラリ使用時に遭遇する「認識されないISO形式」という非推奨警告について、その原因、影響、解決策をJavaScript、jQuery、Moment. jsの観点から詳しく解説します。警告内容と原因この警告は、Moment...


Create React App:Webpack設定による自動更新問題

ファイル監視の設定:CRAはデフォルトでファイル監視機能を使っており、ファイルに変更があると自動的にブラウザを更新します。しかし、まれにこの機能が正しく動作しない場合があります。解決策:node_modules/.bin/webpack-dev-server を再起動する: ターミナルで以下のコマンドを実行します。...