🫧
JavaScriptのCapturing&Bubblingについて
これは何
JavaScriptのイベントに関連したコンセプト、Capturing・Bubblingについてざっくりまとめてみました。
(個人開発している最中にtargetとcurrentTargetの違いがあやふやになり調べ物してたのですが、ついでなので関連していそうなCapturingとBubblingというコンセプトについてもまとめてみました、というものです)
References
以下調べるにあたって参考にした動画を記載しておきます。
(👇の動画がかなり網羅的で良いのでまた記憶が怪しくなってきた時の参考に)
Web Dev Simplified
Capturing & Bubbling
-
ユーザーがDOMのどこかをクリックしたり、マウスをホバーさせたりするようなinteractionは総称して
eventと呼ばれている- こうした
eventに応じて何かアクションを起こしたい場合、event handlerと呼ばれるような関数を作成しそれをaddEventListnerとかで発火するように実装したりする
- こうした
-
で、どの
eventも発生すると以下2つのフェーズを経て上記addEventListenerで登録した処理を実行していく

- Capturing:DOMの外側からイベントが起こった対象のelementに向かって処理を実行していくフェーズ
- Bubbling:- イベントが起こった対象のelementからDOMの外側に向かって処理を実行していくフェーズ
- デフォルトだと
addEventListenerは、2番目の引数として渡された関数をBubblingフェーズで発火させる設定になっている
sample.addEventListener("click", () => {
console.log("clicked!");
});
// 3番目の引数が省略されているだけで実際はcaptureの設定がオフ = Bubblingで発火させる設定になっている
// sample.addEventListener("click", () => {
// console.log("clicked!");
// }, { capture: false });
以下わかりやすいようにデモを作ってみました。
このデモだと真ん中のson にあたるdivをクリックするとson にaddEveneListenerで登録した処理に続いてdad, granpa の処理も走ります。
これはこの時以下のような順序で処理が走っているのが理由。
- クリックをされた対象のelement
sonに向かってDOMの外側からCapturingのフェーズが発生 -
granpa,dadにもaddEventListenerで処理が登録されているけど、いずれもデフォルトではcapure: falseのためCapturingフェーズでは素通り - イベントの対象である
sonに到達し、今度はsonから外側にむけて処理が走っていくBubblingフェーズに - ここで初めて
sonに登録された処理がはしる - そして最初は素通りした
dad,granpaの処理もこの外側に向かってBubble upしていく過程で実行されていく
中身のコードはこちら
const granpa = document.getElementById("granpa") as HTMLElement;
const dad = document.getElementById("dad") as HTMLElement;
const son = document.getElementById("son") as HTMLElement;
granpa.addEventListener("click", () => {
console.log("Granpa!");
});
dad.addEventListener("click", () => {
console.log("Dad!");
});
son.addEventListener("click", () => {
console.log("Son!");
});
次にCapturingでもちゃんと処理を走らせることがわかるデモを以下に作成。
こちらのデモではgranpa、dad、 sonそれぞれにCapturingのフェーズでも発火する処理をaddEventListenerでくっつけてあるため、sonをクリックすると以下のような順番で処理が走ります。
Granpa capture!
Dad capture!
Son capture!
Son bubble!
Dad bubble!
Granpa bubble!
granpa.addEventListener(
"click",
() => {
console.log("Granpa capture!");
},
{ capture: true }
);
dad.addEventListener(
"click",
() => {
console.log("Dad capture!");
},
{ capture: true }
);
son.addEventListener(
"click",
() => {
console.log("Son capture!");
},
{ capture: true }
);
granpa.addEventListener("click", () => {
console.log("Granpa bubble!");
});
dad.addEventListener("click", () => {
console.log("Dad bubble!");
});
son.addEventListener("click", () => {
console.log("Son bubble!");
});
以上かなりざっくりとですがCapturingとBubblingについてのメモでした!
Discussion