| Web
イベント定義でonを使ってみよう

このエントリーは軽めのjQuery Advent Calendar 2012の19日目のエントリーです。
jQueryを利用する利点にイベントの処理が書きやすいというのがあります。例えばクリックでアクションを起こすときには
$('hoge').click(function)
という書き方で、対象の要素を指定してしまえば容易にイベントを割り振ることができます。
で、このエントリーのタイトルは「onを使ってみよう」ということですから、
$('hoge').on('click',function);
という形で書けばいいよね。ハイ終了!
…ではなくて今回紹介したいのは
$('fuga').on('click','hoge',function);
という形式のonの利用です。リファレンスの表記で表すと
.on( events , selector , handler(eventObject) )
という形式になります。イベントを設定したい要素の親要素のセレクタを「fuga」に入れ、イベントを設定したい要素を(findの要領で)「hoge」に入れます。
まずは2つのHTMLを用意しました。
テーブルのtd(11111)をクリックするとクリックされた行の背景が切り替わるというものです。一行当たりtdが9個あり、tbodyには100行あるのでイベントを設定するtdの数は900個になります。
背景の切り替えのスクリプトは
function changeActiveState(){
$(this).parent().toggleClass('active');
}
です。
で、tdをクリックした時にイベントを設定する部分は
//Test01
function setEvent(){
$('td').click(changeActiveState);
}
//Test02
function setEvent(){
$('table').on('click','td',changeActiveState);
}
Test02のほうがonを利用した形になります。
で、こちらをIE9 F12開発者ツールのプロファイラー機能で関数ごとの消費時間を表示してくれるので利用してみます。今回、setEventという関数でイベントを定義しているのでその関数の消費時間を計測してみました(当然数値にばらつきが出るのであくまで一例として見て下さい)。
//Test01
setEvent 1 49.00ms
//Test02
setEvent 1 1.00ms
ということで今回のケースでは約50倍早いという結果になりました。ちなみにtdの数を一行40個の4000個にした場合、
//Test01
setEvent 1 155.00ms
//Test02
setEvent 1 1.00ms
という結果になっています。対象の要素が増えても基本的にTest02のケースでは速度に影響がないというのが理解できるかと思います。
どうしてこういった形になるかといいますと、Test01のケースでは実行時に対象の要素全てにイベントの定義を行うのに対して、Test02のケースではtableに対してのみエベントを定義し、tableからイベントのバブリングによって対象の要素に定義されたイベントが起きているかを判定します。結局のところコストをどこにかけるかというところで、Test01ではイベントの定義時にまとめて払ってしまい、Test02の時にはイベントを発生させたい時に(子要素の判定のために)コストをかけるという形になります。なので対象の要素の数でどちらがいいか判断するという形になると思います。
また、Test02の形式には副次的なメリットがあって以前の関数名(今もある)でいうところの「live」の効果が出ます。イベントが発生するごとに対象の子要素か見てくれるのでそうなるわけです。
というわけで
- 対象の要素が多い時
- 対象の要素数がロード後に動的に増えるとき
などは
.on( events , selector , handler(eventObject) )
の形式のイベント定義を検討してみてはいかがでしょうか。
というわけで軽めのjQuery Advent Calendar 2012の19日目のエントリーは以上です。明日はto-Rの西畑さんです!