【jQuery】on()でイベントを設定する方法(bind/liveとの違いも解説)

JavaScript

こんにちは、かつコーチです。

前回はcss()メソッドで、要素のスタイルを直接書き換える方法を紹介しました。

スタイルを書き換えるタイミングの多くは、「クリックしたら」「マウスが乗ったら」といったイベント(ユーザーの操作やブラウザの状態変化をきっかけに発生する出来事)がきっかけになります。

今回は、jQueryでイベントを設定する基本メソッドon()について解説します。

基本の書き方

on()の基本構文

on()は、指定した要素にイベントとその処理をまとめて登録するメソッドです。

$('.button').on('click', function () {
  console.log('ボタンがクリックされました');
});

第1引数にイベント名(clickmouseentersubmitなど)、第2引数に発生時の処理(関数)を渡します。

素のJavaScriptのaddEventListenerとほぼ同じ役割だと考えると理解しやすいです。

// 素のJavaScriptで書くとこうなる
document.querySelector('.button').addEventListener('click', function () {
  console.log('ボタンがクリックされました');
});

複数のイベントをまとめて登録する

同じ処理を複数のイベントに登録したい場合、イベント名を半角スペース区切りで並べられます。

$('.box').on('mouseenter mouseleave', function () {
  $(this).toggleClass('is-hover');
});

イベントごとに違う処理を割り当てたいときは、オブジェクト形式で渡す書き方も便利です。

$('.box').on({
  mouseenter: function () {
    $(this).addClass('is-hover');
  },
  mouseleave: function () {
    $(this).removeClass('is-hover');
  }
});

bind・live・delegateとの違い

過去のjQueryにあった書き方

jQuery 1.7より前は、イベント登録の方法が用途によって複数に分かれていました。

メソッド特徴現在の状態
bind()存在する要素にイベントを登録する非推奨・on()に統合
live()動的に追加される要素にも対応(全ドキュメントを監視)廃止済み
delegate()親要素を起点に子要素へイベントを委譲する非推奨・on()に統合

jQuery 1.7以降は、これらすべてがon()に統合されました。

現在新しくコードを書くときにbind()live()を使う理由はなく、on()だけ覚えておけば十分です。

レガシーな保守案件のコードを読むときに、これらのメソッド名が出てきたら「on()の前身」だと理解できれば困りません。

イベント委譲とは何か

on()が過去のメソッドをすべて置き換えられた理由の1つが、イベント委譲(親要素でイベントを受け取り、実際に操作された子要素を後から判定する仕組み)に対応している点です。

// 親要素(常に存在する)にイベントを登録し、第2引数で対象の子要素を絞り込む
$('.list').on('click', '.list__item', function () {
  console.log('クリックされた項目:', $(this).text());
});

この書き方をしておくと、後から.listの中に.list__itemが追加されても、追加のイベント登録なしにクリックを検知できます。

つまずきやすいポイント:動的に追加した要素でイベントが発火しない

私が実際にハマった経験

私が最初にリスト項目の削除ボタンを実装したとき、Ajaxで新しく追加した項目のボタンだけクリックが反応しない、という現象にハマりました。

最初に画面にあった項目のボタンは問題なく動くのに、後からappend()で追加した項目だけ無反応で、原因が分からず小一時間悩んだ記憶があります。

結論としては、要素を指定する第1引数に対して直接on()を呼んでいたことが原因でした。

❌ Before:追加された要素に直接on()を呼んでいる

$('.list__item .delete-button').on('click', function () {
  $(this).closest('.list__item').remove();
});
// この時点で存在する.delete-buttonにしかイベントが付かない
// 後からappend()で追加したボタンには反応しない

on()は呼び出された時点でDOMに存在する要素にしかイベントを登録しません。

後から追加された要素は、この処理が終わった後に生まれているため、対象に含まれないのです。

✅ After:親要素を起点にイベント委譲する

$('.list').on('click', '.delete-button', function () {
  $(this).closest('.list__item').remove();
});
// .listは最初から存在するので、その中に後から追加された
// .delete-buttonでもクリックが検知できる

親要素である.list自体は最初から画面に存在しているため、そこにイベントを登録しておけば、子要素がいつ追加されても検知できるようになります。

「動的に追加される要素にイベントを付けたいときは、親を起点に委譲する」と覚えておくと、同じつまずきを避けられます。

応用:イベントの解除とワンタイム実行

off()でイベントを解除する

登録したイベントが不要になった場合はoff()で解除できます。

$('.button').off('click');

one()で1回だけ実行する

「初回クリック時だけ処理を実行したい」というケースではone()が便利です。

$('.button').one('click', function () {
  console.log('この処理は最初の1回だけ実行されます');
});

on()と名前が似ていますが、役割は明確に異なるので混同しないよう注意してください。

まとめ

この記事のポイント

  • on()はイベント登録の基本メソッドで、素のJavaScriptのaddEventListenerに近い役割を持つ
  • bind()live()delegate()は過去の書き方で、現在はすべてon()に統合されている
  • 動的に追加される要素にイベントを付けたいときは、親要素を起点にしたイベント委譲を使う
  • 1回だけ実行したい処理にはone()、解除にはoff()を使う

次に読むべき記事

次回は、アコーディオン(FAQ)の開閉をjQueryで実装しながら、素のJavaScript版との書き方の違いを比較します。

今回学んだon()が、実際のUI実装でどう使われるかを確認していきます。

タイトルとURLをコピーしました