jQueryのイベントハンドリングには、現在 .on()
,.off()
のみが推奨されて利用されています。
その基本的な使い方はこんなかんじでした。
$(element).on(event, function() { console.log('event fired!'); });
この場合、対象となる$(element)
において指定したevent
が発火した時に、コールバック関数が呼び出されます。非常に直感的ですね。
ところで、これは以前の.bind()
と全く同じです。
.bind()
の場合は、指定したずばりその要素に対してのみ、イベントハンドリングを行います。よって、.bind()
が呼び出されたその時点で存在しない要素に対しては、たとえセレクタが一致していたとしてもハンドリングが行われません。
このことを利用すれば、イベントハンドリングをしたいまさにその要素にのみ、たとえその後同じセレクタが生成されてこちらにはイベントハンドリングを行いたくない場合でも、イベントハンドリングを行うことが出来ます。
<div class="parent"> <a id="target"></a> </div>
var $parent = $('.parent'), $a = $parent.find('a'); $a.on('click', function() { console.log($(this).attr('id')); }); var $dom = $('<a id="notTarget"></a>'); $parent.append($dom); // #target をクリックするとイベント発火 // #notTarget をクリックしてもイベント発火しない
delegate使う
delegateってなにかっていうと、親要素に対してイベントハンドリングを一度だけ行って、その子要素を監視する感じのやつです。
言葉で説明してもわかりにくい系の概念なので、コードを書きます。
<div class="parent"> <a id="target"></a> </div>
var $parent = $('.parent'), selector = 'a'; $parent.on('click', selector, function(e) { console.log($(e.currentTarget).attr('id')); }); var $dom = $('<a id="targetToo"></a>'); $parent.append($dom); // #target をクリックするとイベント発火する // #targetToo をクリックしてもイベント発火する
はい、これでどっちのa
要素をクリックしてもconsole.log
流れます。
要は、いつ対象となるセレクタを持ってる要素が追加されようが、イベントハンドリングした親要素の中に入る限りは、いつだってイベント発火でコールバック関数を呼べるようになるんです。
これは特にajaxでバンバン要素を追加したり削除したりするようなwebアプリケーションで効果を発揮して、かなりメモリを節約出来る感じです。あといちいちイベント張らなくていいので、管理がものすごい楽です。コードも綺麗になる気がします。
delegateとlive
ところで.delegate()
の他に.live()
っていうメソッドも実はあります。ありますが、ほとんどやってることは同じで、親要素が特定のセレクタなのか、document
なのか、というくらいしか違いがない(と僕は認識してる)ので、.on()
を使ってる限りは意識する必要ないです。
ただ、on()
の場合は書式が統一されていますが、.bind()
, .delegate()
, .live()
はそれぞれ書式が全然違うので、覚えることが増えて面倒なので.on()
で統一するのが楽です。というか.on()
が公式で推奨してるメソッドなので.on()
にしましょう。
.off()
特にナニも言うことはありません。
普通に使って下さい。
うそです。.off()
は実は.on()
よりもわかりにくいメソッドな気がしているのでき
ちんと整理してみます。
まず、すべてのイベントを削除する場合。
$(element).off();
これでこの要素に紐付いたイベントは全て削除されます。全て削除されるので、下手に使うとライブラリ側がハンドリングしたイベントまで削除されたりして、非常に危険なので非推奨です。
$(element).off(event);
これで特定のイベントだけ削除できます。これでも、だいぶ被害の範囲は少なくなりそうですが、まだまだ油断できません。
$(element).off(event + '.namespace');
はい、これで確実に安全です。jQueryのイベントハンドリングでは、各イベントに対してnamespace
を指定できます。こんなかんじに。
$('a').on('click.myEventSpace', function() { console.log('fire'); }); $('a').on('click.hisEventSpace', function() { console.log('he is Jhon Do'); });
このときa
要素をクリックすれば当然二つのログが流れるわけですが、この後更に
$('a').off('click.myEventSpace');
としてやると、それ以後a
をクリックしてもhe is Jhon Do
とだけ流れて、1つ目のイベントのコールバック関数は実行されなくなります。
これがjQueryがもつイベントのnamespace
です。これを適切に利用できれば、余計なイベントハンドラーを削除しなくてすみそうです。
delegate
delegate
でハンドリングしたイベントについて考えましょう。
考えたいですが、ここまでくればとても簡単なのでサクッと書きます。
$(parentElement).off(event, selector);
こうです。要するに.on()
の書式はおなじです。
また、delegate
したイベントハンドラーのすべてを削除したい場合は、
$(parentElement).off(event, '**');
とすることもできます。この場合、delegate
じゃないイベントについては削除されません。
さらに、.on()
のコールバックを設定するときに特定の有名関数を使っていた場合は、その関数名を指定することでその関数だけを削除することが出来ます。
$(parentElement).off(event, selector, functionName);
簡単ですね。
まとめ
.on()
と.off()
は古いバージョンのjQueryでいうところの、
.bind()
・.live()
・.delegate()
の三つのメソッドを共通の書式で書けるように統合した便利な感じのメソッド。
それぞれの性質を理解した上で使えばより一層便利できれいな感じにコードを書ける。
あとnamespace
は大事。