JavaScript

The JavaScript dispatchEvent() method fires an event on an EventTarget, letting you trigger custom or built-in event flows (capture/bubble) in a controlled way for UI, components, and tests.

dispatchEvent

dispatchEvent は「イベントを自分で発火させる」ためのAPIで、伝播(キャプチャ/バブル)と preventDefault() の結果まで含めて制御できます。

このページでできるようになること

まずは直感:dispatchEvent って何?

ざっくり言うと、dispatchEvent は「ユーザーが操作した“ことにする”」ではなく、「イベントという通知をDOMに流す」ためのスイッチです。

正確な定義(仕様に沿った説明)

何のために存在するか

dispatchEvent は、EventTarget(DOM要素、documentwindow など)に対してイベントを発火し、登録済みのイベントリスナーを呼び出すためのメソッドです。

何に適用されるか(対象)

dispatchEventEventTarget を実装するオブジェクトで使えます。典型例は要素(HTMLElement)ですが、documentwindowAbortSignal などにもイベント設計の考え方が流用できます。

できること / できないこと(制約)

できること
  • 任意の Event / CustomEvent を発火し、リスナーを順番(キャプチャ→ターゲット→バブル)で実行する
  • cancelable: true のイベントなら preventDefault() によるキャンセルを反映し、戻り値で結果を受け取れる
  • bubbles: true で親要素へ伝播させ、コンポーネント間の通知に使える
できないこと(重要)
  • ユーザー操作と同等の“信頼されたイベント”にすること(event.isTrusted は基本 false
  • ブラウザが制限している既定動作(例:一部の全画面、クリップボード、ポップアップ)を解除すること
  • 「イベントを投げたら何でも起きる」ようにすること(既定動作はイベント種別・要素・ブラウザ仕様に依存)

影響範囲(レイアウト/描画/ユーザー操作/アクセシビリティ)

レイアウト
dispatchEvent 自体はレイアウトを直接変更しませんが、リスナー内でDOM変更をすれば再計算が起きます(実務では「イベント→DOM更新→再描画」の流れで理解します)。
描画
イベントを発火しただけで描画が変わるのではなく、リスナーがクラス付け替え等をした結果として変わります。
ユーザー操作
ユーザー操作を“再現”する目的に見えても、isTrusted の違いがあり、セキュリティ上の制約が残ります。操作の代用ではなく、通知の設計として使います。
アクセシビリティ
イベントを使ったUIは、キーボード操作(TabEnterSpace)やフォーカス移動も含めて成立させます。イベントだけで状態が変わるUIは、状態の可視化(aria-* 等)もセットで確認します。

基本の書き方(最短の型)

最小サンプル(コピペ用)

JavaScript

const target = document.querySelector("#target");

target.addEventListener("ping", (e) => {
    console.log("ping!", e.detail);
});

const ev = new CustomEvent("ping", {
    detail: { from: "dispatchEvent" },
    bubbles: true
});

target.dispatchEvent(ev);

まずは「CustomEvent を作る → dispatchEvent で流す」を覚えるのが最短です。

よく使うオプション/典型パターン

親にも届かせたい
{ bubbles: true }(親要素にバブルする)
キャンセルできる通知にしたい
{ cancelable: true }(リスナーで preventDefault() を許可)
Shadow DOM の外にも出したい
{ composed: true }(影DOM境界を越えられる。設計判断が必要)
データを渡したい
new CustomEvent("name", { detail: ... })

仕様として押さえるポイント(初心者が事故りやすい所)

戻り値は何?(boolean)
dispatchEvent(event)キャンセルされなかったら trueキャンセルされたら false を返します。キャンセル判定は「cancelable: true のイベントで preventDefault() が呼ばれたか」で決まります。
bubblesfalse だと?
ターゲット要素で止まり、親へは届きません。イベント委譲(親でまとめて受ける)の前提が崩れるので、設計として意図が必要です。
cancelablefalse だと?
preventDefault() を呼んでも defaultPrevented が立たず、戻り値も変わりません。「止めたつもり」が事故になります。
composed はいつ要る?
Shadow DOM の内外をまたぐ設計で必要になります。外へ出したい通知だけ composed: true にし、むやみに公開範囲を広げないのが安全です。
isTrusted は?
dispatchEvent で作ったイベントは多くの場合 isTrusted: false です。権限が絡む機能(ポップアップ、クリップボード等)はユーザー操作が必須のことがあり、テストと本番を混同しないようにします。
同じ Event を使い回せる?
基本は避けます。イベントオブジェクトは一度の発火で使い切るつもりで、新しく生成して流すのが安全です。

よくある勘違い・混同ポイント

dispatchEvent = ユーザー操作の再現
違います。ユーザー操作は入力デバイス、既定動作、セキュリティ制約まで含みます。dispatchEvent は「イベント通知」を流すだけです。
preventDefault() = 親への伝播を止める
違います。伝播を止めるのは stopPropagation() です。preventDefault() は「既定動作のキャンセル」です(ただし cancelable が必要)。
bubbles: true なら必ず親で受けられる
親側のリスナーが正しい型で登録されている必要があります(キャプチャ/バブル、要素がDOMツリー上にあるか、Shadow DOM境界など)。
「イベント委譲」なら何でも速い
イベントの種類によってはバブルしない/挙動が特殊です。性能は「リスナー数」「発火頻度」「DOM更新の重さ」もセットで見ます(試験対策:計算量というより“定数が効く”系)。

実務でよくある使用例(制作会社の現場を想定)

コンポーネント内部の状態変化を外へ通知する
UI部品の内部で値が変わったとき、CustomEventdetail に値を載せ、親側が購読する形にします(依存を減らして再利用しやすい)。

JavaScript

function emitChange(el, value) {
    el.dispatchEvent(new CustomEvent("widget:change", {
        detail: { value },
        bubbles: true
    }));
}
フォーム部品のバリデーションを「イベント」で統一する
入力、変更、送信の手前など、検証のタイミングをイベント名で統一すると、実装が散らばりにくいです(ただし既定動作の扱いは慎重に)。
テストで「通知が出るか」を検証する
実ユーザー操作はE2E、通知の有無はユニットテスト、と分けると安定します。dispatchEvent はユニット側で使われがちです。

実務で起きがちな事故と回避策

発火したのに親で受け取れない
  • bubblesfalse になっていないか
  • 親のリスナーがキャプチャ(第3引数 true)前提になっていないか
  • ターゲット要素が想定のDOMツリー上にあるか(差し替え/再生成で参照が古いことがある)
DevTools では、発火元要素にブレークポイント(Event Listener Breakpoints)を置くと追いやすいです。
preventDefault() したのに止まらない
  • イベントが cancelable: true か(event.cancelable を確認)
  • 既定動作の“本体”が別の場所にある(例:フォーム送信をコードで呼んでいる)
イベントが二重に走る
  • 同じ要素に複数回 addEventListener していないか(初期化の重複)
  • 親と子の両方で受けていて、バブルで重複したように見えていないか
通知の設計が肥大化する
イベント名・detail の形・公開範囲(bubbles/composed)をルール化し、コンポーネントが勝手に増えないようにします。

アクセシビリティ/UX観点での注意(必要な範囲で)

関連API・関連概念(相互作用)

addEventListener
受け手を登録する。第3引数(または { capture: true })でキャプチャを切り替える。
CustomEvent
detail でデータを渡せる。アプリ独自の通知に向く。
stopPropagation / stopImmediatePropagation
伝播を止める(既定動作は止めない)。
preventDefault
既定動作のキャンセル(cancelable が必要)。
試験対策:イベントループ / タスクキュー
イベントは「発火→リスナー実行」が同期で起きるように見えても、実際には入力やタイマー等でキューに積まれてから処理されます。dispatchEvent は“今その場で”通知を流すので、非同期の前提と混ぜるとバグが出ます。

FE整理(用語・ひっかけ・ミニ問題)

用語

ミニ問題

Q1. dispatchEvent の戻り値が false になる条件は? A. cancelable: true のイベントで、どこかのリスナーが preventDefault() したときです。
Q2. 親でまとめて受けたいのに届きません。最初に疑うべきフラグは? A. bubbles です。false なら親へは届きません。
Q3. preventDefault()stopPropagation() の違いは? A. preventDefault() は既定動作のキャンセル、stopPropagation() は親への伝播を止めます。
Q4. セキュリティ的に「ユーザー操作が必要」な機能が動きません。なぜ? A. dispatchEvent で作ったイベントは多くの場合 isTrustedfalse で、ブラウザが権限系操作を許可しないためです。

FAQ(よくある質問)

Q. dispatchEvent(new Event("click"))element.click() は同じですか?
A. 同じではありません。dispatchEvent はイベント通知を流すだけで、click() は要素のクリック挙動(仕様に基づく処理)を伴うことがあります。
Q. 戻り値が true / false になるのが分かりません。
A. cancelable: true のときだけ「キャンセルされたか」を見ます。キャンセルされていなければ truepreventDefault() が実行されれば false です。
Q. 親で受けたいのに届きません。
A. bubblestrue か、親のリスナーの登録場所(キャプチャ/バブル)と要素ツリーが想定どおりかを確認します。
Q. 「本番では動くのに、テストで動かない」ことがあります。
A. ユーザー操作由来の isTrusted の違いや、レイアウト計算・フォーカス等の環境差で起きます。通知(dispatchEvent)とUI操作(E2E)を分けて検証します。

症状早見(最短で切り分ける)

症状:親でイベントが取れない
原因候補:bubbles: false / 要素がDOM外 / Shadow DOM境界。確認:ログで event.bubblesevent.composed を見る。
症状:preventDefault() が効かない
原因候補:cancelable: false / 既定動作が別経路。確認:event.cancelableevent.defaultPrevented を見る。
症状:二重に呼ばれる
原因候補:二重登録 / バブルで重複。確認:DevTools の Event Listeners と、どの要素で受けているか。
症状:権限系APIが動かない
原因候補:isTrusted: false でブロック。確認:event.isTrusted とブラウザコンソールの警告。

まとめ:迷ったときの判断軸(短いチェックリスト)