event.stopPropagation()とは?使い方を解説します!【JavaScript】

event.stopPropagation()は、JavaScriptのイベント処理において、イベント伝搬を防ぐためのメソッドです。

この記事ではJavaScriptの『event.stopPropagation()』について、以下の内容をサンプルコードを用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです。

  • event.stopPropagation()とは
  • event.stopPropagation()メソッドの使い方
    • バブリングフェーズのイベント伝搬を防ぐ
    • キャプチャリングフェーズのイベント伝搬を防ぐ
  • event.stopPropagation()event.stopImmediatePropagation()の違い

event.stopPropagation()とは

event.stopPropagation()は、その名の通り、eventpropagation(伝搬)をstop(停止)するメソッドです。

JavaScriptでは、デフォルトではイベントが発生した要素(ターゲット要素)から親要素にイベントが伝搬します。イベントが発生して、呼び出されたイベントリスナーの中でevent.stopPropagation()を呼び出すと、これ以降のイベントの伝搬を停止させることができます。

以下に示すようにevent.stopPropagation()を用います。

document.getElementById('xxx').addEventListener('イベント動作(clickやsubmitなど)', function(event){
    event.stopPropagation(); // イベントの伝搬を停止する
    // ここにカスタムの処理を記述
});

event.stopPropagation()を用いると、「バブリングフェーズ」と「キャプチャリングフェーズ」のどちらの場合でもイベントの伝搬を防ぐことができますが、「バブリングフェーズ」でevent.stopPropagation()を用いるケースの方が多いです。

  • バブリングフェーズ:イベントがターゲット要素から親要素へ向かって伝播するフェーズ。
  • キャプチャリングフェーズ:イベントが親要素からターゲット要素に向かって伝播するフェーズ。

event.stopPropagation()の使い方

event.stopPropagation()について、以下に示している使い方をこれから説明します。

  • バブリングフェーズのイベント伝搬を防ぐ
  • キャプチャリングフェーズのイベント伝搬を防ぐ

上記の使い方について順番に説明します。

バブリングフェーズのイベント伝搬を防ぐ

以下のサンプルコードでは、event.stopPropagation()を用いて、子要素のclickイベント発生時に親要素にイベントが伝播するのを停止しています。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="parent" style="padding: 20px; background-color: lightgray">
      親要素
      <div id="child" style="padding: 20px; background-color: lightblue">
        子要素
      </div>
    </div>

    <script>
      document.getElementById('parent').addEventListener('click', function () {
        alert('親要素がクリックされました');
      });

      document.getElementById('child').addEventListener('click', function (event) {
        event.stopPropagation();
        alert('子要素がクリックされました');
      });
    </script>
  </body>
</html>

上記のサンプルコードでは、子要素をクリックしても親要素のクリックイベントが発生しないため、親要素のアラートが表示されません。

キャプチャリングフェーズのイベント伝搬を防ぐ

以下のサンプルコードでは、event.stopPropagation()を用いて、キャプチャリングフェーズでイベントを伝搬しないようにしています。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="grandparent" style="padding: 20px; background-color: lightcoral">
      祖父要素
      <div id="parent" style="padding: 20px; background-color: lightgray">
        親要素
        <div id="child" style="padding: 20px; background-color: lightblue">
          子要素
        </div>
      </div>
    </div>
  </body>
  
  <script>
    // キャプチャリングフェーズのリスナー(祖父要素)
    document.getElementById('grandparent').addEventListener('click', function() {
        alert('キャプチャリングフェーズで祖父要素がクリックされました');
    }, true); // 第三引数にtrueを渡すことでキャプチャリングフェーズのリスナーになる

    // キャプチャリングフェーズのリスナー(親要素)
    document.getElementById('parent').addEventListener('click', function(event) {
        event.stopPropagation();
        alert('キャプチャリングフェーズで親要素がクリックされました');
    }, true); // 第三引数にtrueを渡すことでキャプチャリングフェーズのリスナーになる

    // 子要素
    document.getElementById('child').addEventListener('click', function() {
        alert('子要素がクリックされました');
    });
</script>
</html>

上記のサンプルコードでは、子要素をクリックすると、キャプチャリングフェーズが開始します。

祖父要素のキャプチャリングフェーズのイベントリスナーが最初に呼び出され、アラート「キャプチャリングフェーズで祖父要素がクリックされました」が表示されます。

次に、親要素のキャプチャリングフェーズのイベントリスナーが呼び出され、アラート「キャプチャリングフェーズで親要素がクリックされました」が表示されます。親要素のイベントリスナー内でevent.stopPropagation()が呼び出されるため、キャプチャリングフェーズでのイベントの伝搬が停止され、子要素のアラートが表示されません(イベントの伝搬が祖父要素→親要素で停止する)。

event.stopPropagation()とevent.stopImmediatePropagation()の違い

event.stopPropagation()はバブリングフェーズとキャプチャリングフェーズのイベント伝搬を停止しますが、現在の要素に登録された他のイベントリスナーは呼び出されます。一方、event.stopImmediatePropagation()は、現在の要素に登録された他のイベントリスナーの呼び出しも停止します。

addEventListener()でイベントリスナーを登録する際、同じターゲットの同じイベントに対して複数のイベントリスナーを登録することができます。複数イベントリスナーを登録した場合、イベントが発生すると登録された順番にイベントリスナーが呼び出されます。

イベントリスナーの中でevent.stopImmediatePropagation()を実行すると、同じターゲットの同じイベントに登録されているまだ呼び出されていないイベントリスナーが呼び出されなくなります。またevent.stopPropagation()メソッドを実行したときと同じように親要素へのイベント伝搬も行われなくなります。

では実際に、event.stopPropagation()event.stopImmediatePropagation()を用いたサンプルコードで動作の違いを確認してみましょう。

event.stopPropagation()を用いたサンプルコード

以下のサンプルコードでは、event.stopPropagation()を使用しています。これにより、バブリングフェーズのイベント伝搬は停止しますが、同じ要素に登録された他のイベントリスナーは呼び出されます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="parent" style="padding: 20px; background-color: lightgray">
      親要素
      <div id="child" style="padding: 20px; background-color: lightblue">
        子要素
      </div>
    </div>

    <script>
      document.getElementById('parent').addEventListener('click', function () {
        alert('親要素がクリックされました');
      });

      document.getElementById('child').addEventListener('click', function (event) {
        event.stopPropagation();
        alert('子要素の最初のリスナーがクリックされました');
      });

      document.getElementById('child').addEventListener('click', function () {
        alert('子要素の二番目のリスナーがクリックされました');
      });
    </script>
  </body>
</html>

上記の例では、event.stopPropagation()を呼び出しているため、親要素のイベントリスナーは呼び出されませんが、子要素に登録された二番目のイベントリスナーは呼び出されます。

event.stopImmediatePropagation()を用いたサンプルコード

以下のサンプルコードでは、event.stopImmediatePropagation()を使用しています。これにより、バブリングフェーズのイベント伝搬は停止します。また、同じ要素に登録された他のイベントリスナーの呼び出しも停止します。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="parent" style="padding: 20px; background-color: lightgray">
      親要素
      <div id="child" style="padding: 20px; background-color: lightblue">
        子要素
      </div>
    </div>

    <script>
      document.getElementById('parent').addEventListener('click', function () {
        alert('親要素がクリックされました');
      });

      document.getElementById('child').addEventListener('click', function (event) {
        event.stopImmediatePropagation();
        alert('子要素の最初のリスナーがクリックされました');
      });

      document.getElementById('child').addEventListener('click', function () {
        alert('子要素の二番目のリスナーがクリックされました');
      });
    </script>
  </body>
</html>

上記の例では、event.stopImmediatePropagation()を呼び出しているため、親要素のイベントリスナーは呼び出されません。また、子要素に登録された二番目のイベントリスナーも呼び出されません。

本記事のまとめ

この記事ではJavaScriptの『event.stopPropagation()』について、以下の内容を説明しました。

  • event.stopPropagation()とは
  • event.stopPropagation()メソッドの使い方
    • バブリングフェーズのイベント伝搬を防ぐ
    • キャプチャリングフェーズのイベント伝搬を防ぐ
  • event.stopPropagation()event.stopImmediatePropagation()の違い

お読み頂きありがとうございました。