jQueryのon()とclick()でイベントが2回以上重複して実行されるのを防ぐ

くっ。。こんな問題に丸一日消費してしまいました。。悔しくて死にそう。。

今後同じような場面に出くわすかもしれないので、メモを残します。

はじめに

例えば要素のクリックをトリガーに、特定の処理を走らせたいケース。

jQueryだと .on().click() を使いますね。

下記は #hogehoge という要素をクリックした時に input を叩き、ファイルを選択した際にゴニョゴニョする。みたいなコードです。

$('#hogehgoe').on('click', function() {
  $('input[type=file]').click()
  $('input[type=file]').on('change', function(e) {
    ...
  }
}

この書き方だと $('input[type=file]').on('change'~ の処理が2回、3回と重複して実行されました。

1回目のクリックでは1回実行され、2回目のクリックで2回、3回目のクリック3回、とイベントの発火回数が増えていきます。

.on() はDOMにイベントを追加するメソッドなのですが、同じ要素に対して同じイベントを複数登録できてしまうため、このようなことが起きてしまいます。

解決策

この問題を解決するには、追加したイベントを .off() で除去します。

$('#hogehgoe').on('click', function() {
  $('input[type=file]').click()
  $('input[type=file]').off('change')
  $('input[type=file]').on('change', function(e) {
    ...
  }
}

input[type=file] に登録されたイベントが毎回リセットされるので、重複実行を防ぐことができます。

もちろんメソッドチェーン的に繋げる書き方もOKです。

$('#hogehgoe').on('click', function() {
  $('input[type=file]').click()
  $('input[type=file]').off('change').on('change', function(e) {
    ...
  }
}

まとめ

いい感じに処理できるようになりました。やったね!

そして次のプログラミングが始まるのです!