【JavaScript】イベントにおけるバブリング(bubbling)とは?挙動と、停止する方法

JavaScript

JavaScript中級者ともなると、バブリングという言葉を耳にしたことはあるはずです。文字通り英語では「Bubbling」と書き、泡が水面まで登っていく様子を模したプログラム用語です。

悩見坂 楓
悩見坂 楓

バブリングってあれか、MJが飼ってたおさるさんね

著者
著者

音楽については博識だね。バブルス君知っている人いるのかしら。

バブリング(Bubbling)とは何か?

結論を言うと、複数の要素で包含されている、一番真ん中の要素のイベントが発火すると、それを囲んでる要素達も次々と発火してしまう現象、とでも言いましょうか。

ちなみにバブリングは日本では「伝播(でんぱ)」とも言います。

分かりにくいかと思いますので簡単なサンプルを掲載してみましょう。

バブリングが発現するサンプル

クリックしてみてね

囲みDIV-02 alert(‘level 3’)を仕込んでいるよ
囲みDIV-01 alert(‘level 2’)を仕込んでいるよ

真ん中の白をクリックしてね。alert(‘level 1’)だよ。

<p>クリックしてみてね</p>
<div class="c line-wrapping" onclick="alert('level 3')"><strong>囲みDIV-02</strong> alert('level 3')を仕込んでいるよ
  <div class="b line-wrapping" onclick="alert('level 2')"><strong>囲みDIV-01</strong> alert('level 2')を仕込んでいるよ
    <p class="a line-wrapping" onclick="alert('level 1')">真ん中の白をクリックしてね。alert('level 1')だよ。</p>
  </div>
</div>
  .line-wrapping {
    margin: 10px;
    border: 1px solid #DDD;
  }
  .line-wrapping:hover {
    cursor: pointer;
  }
  .c.line-wrapping {
    background-color: #333;
    color: #FFF;
  }
  .c.line-wrapping:hover {
    background-color: #d90368;
    color: #FFF;
  }
  .b.line-wrapping{
    background-color: #BBB;
  }
  .b.line-wrapping:hover{
    background-color: #333;
  }
  .a.line-wrapping{
    background-color: #FFF;
    color: #666;
    text-align: center;
  }
  .a.line-wrapping:hover{
    background-color: #333;
    color: #FFF;
  }

まずは、大外を囲っている「囲みDIV-02」をクリックするとonclick=”alert(‘level 3’)”が発火して、アラートは1つしか出ませんね。これはOK。

しかし、しかし、1つ内側にある「囲みDIV-01」をクリックするとあらどうでしょう。「level 2」の後に「level 3」がアラートとして処理されてしまいました…
さらには一番真ん中のエリアに至っては「level 1」→「level 2」→「leve 3」の順に問答無用でアラートが出てきますね。

そう、これがJavaScritpにおけるバブリング(Bubbling)です。真ん中を押したときは「level 1」だけアラートされると思うでしょ??違うんですよこれが、、、おそらく初心者でハマった方も多いのではないでしょうか。

一番下(内側)にある孫要素のonclickが発火すると、それを覆っている親要素、先祖要素も発火してしまう困ったちゃんがバブリング、伝播なのですね。

バブリングを制御して、真ん中のalert()だけだしたい!

サンプル2

囲みDIV-02 alert(‘level 3’)を仕込んでいるよ
囲みDIV-01 alert(‘level 2’)を仕込んでいるよ

真ん中の白をクリックしてね。alert(‘level 1’)だよ。

<p>サンプル2</p>
<div class="c line-wrapping" onclick="alert('level 3')"><strong>囲みDIV-02</strong> alert('level 3')を仕込んでいるよ
  <div class="b line-wrapping" onclick="alert('level 2')"><strong>囲みDIV-01</strong> alert('level 2')を仕込んでいるよ
    <p class="a line-wrapping" onclick="alert('level 1');event.stopPropagation();">真ん中の白をクリックしてね。alert('level 1')だよ。</p>
  </div>
</div>

上記のサンプル2では中央の要素をクリックすると「level 1」というアラートのみが出ます。「level 2」「level 3」というアラートは出ませんね。

今回は複雑なプログラムは考慮しない前提でご説明していますので、最も簡単な方法をご紹介します。それは「event.stopPropagation();」を仕込む方法です。この方法によってバブリングがキャンセルされるのです。

中央(ど真ん中)のonclickには「event.stopPropagation();」をalert();の直後に置いただけです。これで、親要素、先祖要素のonclickが発火しなくなります。
注意としては、このサンプルが最も単純であることを念頭においてください。業務で使う比較的大きなプロジェクトレベルでは、event.stopPropagation();がまた別の不具合をもたらす可能性もあるということです。詳しい例は長くなりますので割愛しますが、本当に必要か、他のイベントに影響が無いか、を必ず確認してうまく利用することをおすすめします。

イベントの伝播を阻止するevent.stopPropagation();とは?

stopPropagationは「stop(ストップする)」「Propagation(伝播、伝搬を)」と和訳出来ます。そのまんまなので覚えやすいですね。文字通りバブリングをキャンセルする働きがあります。伝播をストップさせたい時にはevent.stopPropagation();が活躍します。

使えるブラウザは先日お亡くなりになったInternetExplorerを含め、どのブラウザでも対応可能です。

Eventインターフェースのメソッドなので先頭にevent.を付けて使います。Eventインターフェースについてはまたの機会に別記事にしたいと思います。

まとめ

JavaScriptのバブリングについて浅ーめ、浅ーめに紹介しました。たぶん理解はできたかな、と思います。実際の業務ではjQuery禁止だったり、JavaScriptの実行はHTML内のonclickでのみ実行させる、などの制約があることがあるかと思います。親要素でもonclick、その子要素でもonclickというような実装は出来るだけ避けなければなりませんが、やむを得ない場面も必ずあるはずです。そんな時にこのバブリングとstopPropagation()を知っておけば、怖がる必要もなくなるので、是非頭にインプットしておいてください。では、よいJSライフを!

タイトルとURLをコピーしました