キャプチャフェーズとバブリングフェーズ
イベントが DOM 内をどのように伝わるかを理解します。
「キャプチャフェーズとバブリングフェーズ」はCoddyKit上の無料JavaScript Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJavaScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 JavaScript Academyコースには全4レッスンが含まれています。
DOM を通る2つの経路
要素をクリックしたとき、イベントはその要素だけで発生するわけではありません。イベントは DOM ツリーを2つのフェーズで通過します。キャプチャフェーズでは document からターゲットへ上から下に進み、バブルフェーズではターゲットから document へ下から上に進みます。
<div id="outer">
<button id="inner">Click</button>
</div>デフォルト: バブリング
デフォルトでは、addEventListener はバブルフェーズでリッスンします。内側のボタンをクリックすると、まずそのハンドラーが実行され、次に親のハンドラー、さらに祖父母にあたる要素のハンドラーという順に、document まで実行されます。
inner.addEventListener("click", () => console.log("inner"));
outer.addEventListener("click", () => console.log("outer"));
// Click inner -> logs: "inner" then "outer"キャプチャを有効にする
代わりにキャプチャフェーズでリッスンするには、3番目の引数として true または { capture: true } を渡します。キャプチャハンドラーは、バブルハンドラーより先に上から下へ実行されます。
outer.addEventListener("click", () => console.log("outer capture"), true);
inner.addEventListener("click", () => console.log("inner bubble"));
// Click inner -> "outer capture" then "inner bubble"完全な実行順序
#inner のクリックに対して両方のフェーズのハンドラーがある場合、実行順序は、キャプチャフェーズの上から下、ターゲット、そしてバブルフェーズの下から上です。
- document のキャプチャ
- outer のキャプチャ
- inner(ターゲット)
- outer のバブル
- document のバブル
event.target と event.currentTarget
event.target は、実際にイベントを発生させた要素、つまりクリックが起きた場所です。event.currentTarget は、現在リスナーが実行されている要素です。バブリング中の親のハンドラーでは、これらは異なります。
outer.addEventListener("click", (e) => {
console.log(e.target.id); // "inner" - where click occurred
console.log(e.currentTarget.id); // "outer" - listener owner
});伝播を停止する
event.stopPropagation() はイベントの進行を停止します。イベントは現在のフェーズで次の要素へ進まなくなり、ツリーの上位にある親のハンドラーも実行されません。
inner.addEventListener("click", (e) => {
e.stopPropagation();
console.log("handled here only");
});
outer.addEventListener("click", () => console.log("never runs"));stopImmediatePropagation
stopPropagation()を使っても、同じ要素に登録されたほかのリスナーは実行されます。同じ要素に登録されたほかのリスナーもブロックするには、event.stopImmediatePropagation()を使います。
inner.addEventListener("click", (e) => {
e.stopImmediatePropagation();
console.log("first only");
});
inner.addEventListener("click", () => console.log("blocked"));preventDefault は別物です
preventDefault()とstopPropagation()を混同しないでください。preventDefault()はブラウザーのデフォルト動作(リンクの移動やフォームの送信)をキャンセルしますが、イベントのバブリングは停止しません。
link.addEventListener("click", (e) => {
e.preventDefault(); // do not navigate
// event still bubbles to parents
});キャプチャがまれな理由
ほとんどのコードでは、直感的に理解しやすいバブリングを使います。最も具体的な要素が先に反応し、その後でコンテナーがイベントを認識します。親要素が子要素にイベントを認識される前に割り込んだり、イベントを拒否したりする必要がある場合は、キャプチャが役立ちます。
フェーズを確認する
event.eventPhaseを使うと、現在のフェーズを確認できます。1はキャプチャ、2はターゲット、3はバブルです。通常はほとんど必要ありませんが、複雑なリスナーチェーンをデバッグするときに役立ちます。
el.addEventListener("click", (e) => {
console.log(e.eventPhase); // 1, 2, or 3
}, true);すべてのイベントがバブルするわけではありません
ほとんどのUIイベント(click、input、keydown)はバブルします。一方、focus、blur、mouseenterなど、デフォルトではバブルしないイベントもあります。その場合は、バブルするバリエーション(focusin、focusout)か、キャプチャフェーズを使います。
確認問題
イベントフェーズについて理解度を確認します。
まとめ
イベントはキャプチャ(下方向)してからバブリング(上方向)します。リスナーはデフォルトでバブリングを使い、キャプチャにはtrueを渡します。e.targetはイベントの発生元、e.currentTargetはリスナーを所有する要素です。移動を止めるにはstopPropagation()を使い、デフォルト動作をキャンセルするにはpreventDefault()を使います。この2つのフェーズが、イベントデリゲーションの基礎になります。
よくある質問
「キャプチャフェーズとバブリングフェーズ」レッスンは無料ですか?
はい。「キャプチャフェーズとバブリングフェーズ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、JavaScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 JavaScript Academyコースには全4レッスンが含まれています。
「キャプチャフェーズとバブリングフェーズ」で何を学びますか?
イベントが DOM 内をどのように伝わるかを理解します。 ブラウザで直接実行するハンズオンコードでJavaScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
JavaScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJavaScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「キャプチャフェーズとバブリングフェーズ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJavaScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのJavaScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- キャプチャフェーズとバブリングフェーズ
- イベント委譲パターン
- 委譲を使った動的リスト
- カスタムイベント