0Pricing
JavaScript Academy · レッスン

キャプチャフェーズとバブリングフェーズ

イベントが 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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. キャプチャフェーズとバブリングフェーズ
  2. イベント委譲パターン
  3. 委譲を使った動的リスト
  4. カスタムイベント
← JavaScript Academyに戻る