🌟

JavaScript - 動的に生成されるHTML要素にイベントリスナーを登録する方法 (イベントデリゲーション)

2025/01/18に公開

Webフロントの開発で、「初期状態で要素が存在しない場合」に、JavaScriptでその要素にイベントリスナーを登録したいことがあります。その際に使えるのがJavaScriptの機能「イベントデリゲーション(イベント移譲)」です。
今回は、イベントデリゲーションについて学んだことをまとめます。

イベントデリゲーションとは

イベントデリゲーション(イベント移譲)とは、親要素にイベントリスナーを登録し、子要素で発生したイベントをキャッチして処理する技術です。子要素で発生したイベントの処理を、親要素に移譲(デリゲート)するということですね。

例えば、以下のようなHTMLがあります。

<div id="parent">
  <!-- 初期状態で子要素は存在しない -->
</div>
<button id="add-child">Add Child</button>

ボタンクリックで子要素を追加した後に、その要素にイベントを登録したいことがあります。

イベントデリゲーションを実装する

親要素にリスナーを登録して、例として子要素がクリックされた際に出力させます。

<script>
document.addEventListener('DOMContentLoaded', () => {
  const parent = document.getElementById('parent')
  const addChildButton = document.getElementById('add-child')

  // 親要素にリスナー登録
  parent.addEventListener('click', (event) => {
    if (event.target && event.target.classList.contains('child')) {
      alert(`子要素がクリックされました!: ${event.target.textContent}`)
    }
  })

  // ボタンクリック時に子要素を追加
  addChildButton.addEventListener('click', () => {
    const child = document.createElement('div')
    child.textContent = `Child ${parent.children.length + 1}`
    child.classList.add('child')
    parent.appendChild(child)
  })
})
</script>

上記コードは以下の動きをします。

  1. 初期状態は、#parent要素に子要素は存在しない
  2. 親要素にリスナーを登録
  3. ボタンクリック時に、子要素が追加される
  4. 追加された子要素をクリックすると、アラートが出る

実装は以下です。
https://codepen.io/b07nji/pen/pvzZeRZ

イベントデリゲーションの仕組み

イベントデリゲーションとは親要素にイベントリスナーを設定し、子要素で発生したイベントをキャッチして処理する技術です。

これは、イベントバブリング伝播(プロパゲーション) で実現されます。

  1. イベントが発生
    先ほどのコードで、動的に追加された子要素(<div class="child">)がクリックされる
  2. イベントオブジェクトが生成
    ブラウザがeventオブジェクトを生成し、イベント情報(クリックされた要素、イベントタイプなど)を格納する。
  3. イベントが伝播
    イベントは、発生した要素(event.target)から親要素へ伝播する。この、子要素から親要素へ伝播する挙動をイベントバブリングと言います。
  4. 親要素でリスナーが発火
    親要素に登録されたリスナーが、伝播してきたイベントをキャッチする。event.target<div class="child">の場合、処理をする(アラート)

ユースケース

イベントデリゲーションは、以下のようなケースで有効かと思います。

  • 動的に追加される要素へのイベント処理 (今回のケース)
  • 大量の要素にリスナーを設定する場合
  • パフォーマンスやコードの簡潔性が重要な場合

なお、イベントデリゲーションを使わない場合は、子要素に直接リスナーを設定する必要があるので、コードが煩雑になり可読性が悪くなります。

参考

https://developer.mozilla.org/ja/docs/Web/API/Event/target

https://developer.mozilla.org/ja/docs/Learn_web_development/Core/Scripting/Event_bubbling

Discussion