🫧

onClickイベントがhtmlに向かって伝播するンゴ

2023/11/01に公開

バブリングとは

javascriptのイベント(ex. onClickのクリックイベントなど)が親要素に湧き立つ(bubble up)ように伝播(propagate)していくこと。

具体的にどういうこと?

こう言ったコードがあるとします。

<html lang="en"  onClick={() => console.log("htmlがクリックされました!")}>
  <body  className="flex min-h-screen flex-col items-center justify-between p-24"
       onClick={() => console.log("bodyがクリックされました!")}>
    <div onClick={() => console.log("divがクリックされました!")}>
      <button onClick={() => console.log("buttonがクリックされました!")}>クリックしてね!</button>
    </div>
  </body>
</html>

上記のコードの画面はこんな感じ

この時 buttonをクリックするとコンソールには何が出力されるでしょうか?

クリックしたのはbuttonだけだから僕は以下が出力されるだろうと考えていました。

buttonがクリックされました!

では実際やってみます。

!!!!??

なんと全てのonClickがコンソールに出力されました!

このクリックイベントなどが親要素に湧き立つ(bubble up)ように伝播(propagate)していくことがバブリングの正体です

どういう時に困るの?

モーダルの背景の黒い部分をタップしたときに閉じる挙動を実装した時とかに困ります。

以下のような構造でモーダルを実装した時にイベントが伝播してモーダル内の要素をクリックするとモーダルが閉じてしまうという挙動が発生します。

<div className="black_modal_overlay" onClick={() => closeModal()}>
	<div className="modal_container">
		<h1>hello</h1>
		<input / >
	</div>
</div>

このようなDom構造の時にmodal_containerクラスのdivやinputやh1のhelloをクリックするとモーダルが閉じてしまいます。

バブリングというものを知らなかった私はかなり困りました。

なので記事に残して忘れた時に備えようということで今記事書いてます。

どうやってバブリング防ぐの?

イベントが親要素にbubble up(湧き立つ)のを防ぐには伝播(propagate)を止めなければなりません。

伝播を止める

伝播(propagate) を 止める(stop)

そーれ!

ここ stopPropagation()

このメソッドを使用します。
https://developer.mozilla.org/ja/docs/Web/API/Event/stopPropagation

このメソッドはイベントインターフェースのメソッドなので以下のように使用します

<html lang="en"  onClick={() => console.log("htmlがクリックされました!")}>
  <body  className="flex min-h-screen flex-col items-center justify-between p-24"
       onClick={(e) => e.stopPropagation()}> //💡ここでイベントの伝播を止めるよ!
    <div onClick={() => console.log("divがクリックされました!")}>
      <button onClick={() => console.log("buttonがクリックされました!")}>クリックしてね!(e.stopPropagation()を添えて)</button>
    </div>
  </body>
</html>

では実際にイベントが止まるかみてみましょう!

button🔥 > div🔥 > body (e.stopPropagation) > html

buttonとdivのクリックだけが発火しhtmlのクリックは発火していないことがわかります!

ちゃんとイベントの伝播(propagate)を止める(stop)ことができましたね!

ではまた!

ソース(参考資料)

https://developer.mozilla.org/ja/docs/Learn/JavaScript/Building_blocks/Events#イベントのバブリングとキャプチャリング

Discussion