作成日:2025/7/9,最終更新日:2025/7/22

JavaScript TypeScriptのイベント処理【応用編】

イベントオブジェクト、バブリング、イベントデリゲーションまで、より実務的なイベント操作に関する解説

この記事では、JavaScriptのイベント処理について、実務でよく使う応用テクニックを解説します。
イベントオブジェクト、伝播の仕組み、onceオプションや動的要素へのイベント付与など、実務で知っておきたい4つのポイントを中心に紹介していきます。


1. イベントオブジェクトの活用

解説: イベントリスナーで渡される引数(通常 eevent)には、イベントの詳細な情報が入っています。
これを イベントオブジェクト と呼び、クリックした要素や、デフォルト動作を止めるなど、様々な操作に使えます。




● event.target で押された要素を取得

クリックされた要素を取得して表示する例です:

<ul id="fruit_menu">
  <li>りんご</li>
  <li>みかん</li>
  <li>バナナ</li>
</ul>

const menu = document.querySelector('#fruit_menu');
menu.addEventListener('click', (event) => {
  const clicked = event.target;                                 // クリックされた要素を取得
  alert('「' + clicked.textContent + '」がクリックされました'); // クリックされた項目の内容を表示
});

上記のように、イベントオブジェクトの event.target を使えば、押された要素そのものが取得できます。


【実行例】果物リストをクリックしてみよう

  • りんご
  • みかん
  • バナナ

● event.preventDefault() でデフォルト動作を止める

リンクやフォームなど、ブラウザが本来持っている挙動を止めたいときに使います:

<a href="https://webtech-village.jp/" id="test_link">リンク</a>

const link = document.querySelector('#test_link');
link.addEventListener('click', (event) => {
  event.preventDefault();                     // リンク先へ移動しない
  alert('リンクは無効化されました');
});

preventDefault() を使うと、本来の動作をキャンセルできます。
フォーム送信時の確認処理や、ページ遷移を止めたいときによく使われます。


【実行例】リンクをクリックしてみよう(遷移は無効化されます)

リンク

● まとめ

イベントオブジェクトを使うことで、次のようなことが可能になります:

  • ✅ 押されたボタン・要素を特定する(event.target
  • ✅ 本来の動作を止めて処理を制御する(event.preventDefault()

これらは、フォーム・リンク・メニュー処理など実務でも非常に多用されます。ぜひ覚えておきましょう!


2. イベントの伝播(バブリングとキャプチャリング)

解説: JavaScriptのイベントは、要素の階層を上下に伝わる性質があり、これをイベントの伝播と呼びます。
これには、2つのフェーズが存在します:

  • 🔸 キャプチャリングフェーズ: 親 → 子(外から内へ)
  • 🔸 バブリングフェーズ: 子 → 親(内から外へ)

イベントリスナーは通常「バブリングフェーズ」で動作しますが、オプションを指定することでキャプチャリングにも対応できます。




● イベントがバブリングしていく例

クリックイベントが、内側の要素から順に親へ伝わっていく様子です。

<div id="outer">
  <div id="inner">
    ボタン
  </div>
</div>

const outer = document.querySelector('#outer');
const inner = document.querySelector('#inner');

outer.addEventListener('click', () => {
  console.log('outerがクリックされました');
});

inner.addEventListener('click', () => {
  console.log('innerがクリックされました');
});

【出力例(innerをクリックしたときのconsole出力)】

innerがクリックされました
outerがクリックされました

このように、子要素(inner)で発生したイベントが親要素(outer)にも伝わっているのがバブリングです。


● キャプチャリングを有効にする方法

addEventListener の第3引数(またはオプションオブジェクト)で capture: true を指定すると、キャプチャリングフェーズで実行されます。

outer.addEventListener('click', () => {
  console.log('outer(capture)');
}, { capture: true });

inner.addEventListener('click', () => {
  console.log('inner(bubble)');
});

【出力例(innerをクリック)】

outer(capture)
inner(bubble)

このように、キャプチャリングは先に親要素でイベントが発火します。


● event.stopPropagation() で伝播を止める

ある要素でイベントの伝播を途中で止めたい場合は、event.stopPropagation() を使います。

inner.addEventListener('click', (e) => {
  e.stopPropagation();                        // これで外側には伝播しない
  console.log('innerだけ処理されました');
});

これにより、親要素のリスナーは実行されません。親要素のイベントとバッティングさせたくないときなどに有効です。


● まとめ

  • ✅ 通常のイベントは「バブリングフェーズ」で伝播する
  • ✅ オプションを指定すれば「キャプチャリングフェーズ」でも処理できる
  • stopPropagation() を使えば、伝播を途中で止められる

イベントの流れを理解することで、親子要素のイベントの干渉を避ける実装ができるようになります。


3. 一度だけ実行されるイベント({ once: true })

解説: 通常のイベントリスナーは何度でも実行されますが、一度だけ処理したいケースもあります。
そんなときは、{ once: true } を指定することで、イベントリスナーが1回だけ実行された後、自動で無効になる設定が可能です。




● 一度きりのイベントリスナー

ボタンを押したとき、最初の1回だけメッセージを表示する例です:

<button id="onceBtn">1回だけ反応</button>

const onceBtn = document.querySelector('#onceBtn');
onceBtn.addEventListener('click', () => {
  alert('このボタンは1回だけ反応します');
}, { once: true });

上記のように { once: true } をオプションに加えると、1回実行されたあと自動的にイベントが解除されます。


● 2回目以降は無反応

イベントリスナーの解除は自動で行われるため、2回目以降はイベントがバインドされていない状態になります。

【クリック1回目】 → アラートが表示される

【クリック2回目】 → 何も起きない

自分で removeEventListener を書かなくて済むので、一度限りの確認や初回のみの処理にとても便利です。


【実行例】ボタンをクリックしてみよう(1回だけ反応します)


● よくある用途

  • ✅ 初回クリック時にのみ注意メッセージを出す
  • ✅ チュートリアルのステップを1回だけ表示
  • ✅ 重要操作の最初の入力だけ確認する

● 注意:古いブラウザ対応

{ once: true } はモダンブラウザ(Chrome, Firefox, Edgeなど)では対応していますが、古いInternet Explorerではサポートされていないため注意が必要です。
古い環境もサポートしたい場合は、removeEventListener を使って手動で削除しましょう。


● まとめ

{ once: true } は「一度だけ処理して自動で解除したいイベント」にとても便利です。
書き忘れがちな removeEventListener を自動で省略できるので、コードの見通しも良くなります


4. 動的に生成された要素へのイベント(イベントデリゲーション)

解説: JavaScriptでは、あとから動的に追加された要素には、あらかじめ設定しておいたイベントリスナーが反応しないことがあります。
これを解決するのがイベントデリゲーション(委任)というテクニックです。




● 問題例:あとから追加された要素にイベントが効かない

次のコードでは、後から追加された要素にはイベントが効きません。

// ボタンを押すとliが追加される例
const ul = document.querySelector('#myList');
const btn = document.querySelector('#addItemBtn');

btn.addEventListener('click', () => {
  const li = document.createElement('li');
  li.textContent = '新しい項目';
  ul.appendChild(li);
});

const items = document.querySelectorAll('#myList li');
items.forEach(item => {
  item.addEventListener('click', (event) => {
    alert('クリックされました');
  });
});

これでは querySelectorAll で取得した時点に存在する要素しか対象にならないため、あとから追加した要素にはイベントが効きません


【実行例】リストに項目を追加してクリックしてみよう(失敗する例)

  • 元々の項目

● 解決策:イベントを親要素で受け取る

個々の要素にイベントをつける代わりに、「親要素」にイベントリスナーを設定しておき、「子要素」がクリックされた場合も親側で処理を拾う方法 を、イベントデリゲーション(委任)と呼びます。

// 親要素にリスナーを設定(イベントデリゲーション)
ul.addEventListener('click', (event) => {
  if (event.target.tagName === 'LI') {
    alert('「' + event.target.textContent + '」がクリックされました');
  }
});

event.targetを使って、クリックされた具体的な子要素(liなど)を判定しています。
tagNameの戻り値は常に大文字(UPPERCASE)のため、'LI' のように書く必要があります。


【実行例】リストに項目を追加してクリックしてみよう(成功する例)

  • 元々の項目

● よくある用途

  • ✅ 動的に生成されるリスト・ボタンなどのイベント処理
  • ✅ フィルター・ソートなど、UIのクリック反応
  • ✅ SPA(シングルページアプリ)の動的UI操作

● まとめ

イベントデリゲーションを使えば、コードをシンプルに保ちながら、動的に変化するUIにも柔軟に対応できるようになります。
大規模アプリや動的なページ構成では、最重要テクニックの1つといえるでしょう。


5. まとめ:イベント処理を使いこなす

解説: この記事では、イベント処理に関する応用テクニックを段階的に学んできました。
改めて、ここで紹介したポイントを振り返っておきましょう。


● 本記事で学んだポイント

  • event.target により、クリックされた要素を特定する方法
  • event.preventDefault() を使ったデフォルト動作の抑制
  • イベントの伝播(バブリングとキャプチャリング)の仕組みと制御方法
  • { once: true } を使った1回限りのイベント処理
  • イベントデリゲーション による動的要素への対応

これらはすべて、実務でも頻繁に登場するイベント操作です。
特に 伝播とデリゲーション は、動的UIやコンポーネント設計において必須の知識といえるでしょう。


● 実務での活用シーン

  • ✅ 動的なリストやボタンへのイベント処理
  • ✅ 入力フォームでのバリデーション制御
  • ✅ メニューやモーダル、タブなどのUI操作
  • ✅ SPAでのイベント制御・最適化

イベントの流れと仕組みを理解することで、思い通りにユーザーインターフェースを制御できるようになります。
エラーの防止やコードの保守性にも大きく関わる重要なテーマです。


● 次のステップへ

次は、フォーム操作・バリデーションをテーマに、イベントの応用テクニックをさらに実践的に掘り下げていきましょう。
実際の業務でもよく出てくる「ラジオボタン」「セレクトボックス」「入力チェック」などにチャレンジしていきます!