live/bind/delegate/click 非推奨のお知らせ
厳密には非推奨になったのは、 live, die だけで、他のメソッドはそのまま使える。
困った時の公式マニュアル
新旧APIの対応は以下の通り。
$('a').bind('click', myHandler);
$('a').on('click', myHandler);
$('.comment').delegate('a.add', 'click', addNew);
$('.comment').on('click', 'a.add', addNew);
$('a').live('click', fn);
$(document).on('click', 'a', fn);
ついでに bind のソースも見てみる。
function (types, data, fn) {
return this.on(types, null, data, fn);
}
そのまま on 呼んでるだけだった。 orz
jQueryの非推奨メソッドを見ると、知らないメソッドが知らないうちに廃止されていて感慨深い。
$('a').live('click', fn);
$(document).on('click', 'a', fn);
そもそも、これはどういう意味か?
live = document ?
ここでデモ。index.html を参照。
これがいわゆる「イベントの伝播」
document <= 3.click! 一番上まで伝わる
div#parent <= 2.click!
div#child <= 1.click!
$('#child').bind(...)
document <= 3.click!
div#parent <= 2.click!
div#child <= 1.click! イベントリスナ
$('#child').live(...)
document <= 3.click! イベントリスナ イベントの発生元を調べて反応
div#parent <= 2.click!
div#child <= 1.click!
つまり .live のイベントリスナの本体は、document にアタッチしているので、下層の要素が消えたり増えたりしても動く仕組みだった。
document のイベントリスナの中で
if( 元のクリックされた要素 == '#child' ) { ... }
みたいな分岐をしているっぽい。
-
event.preventDefault();
イベントのデフォルト動作を止める。
リンク <a href="#"> とか。 -
event.stopPropagation();
イベントの伝播を止める。
親要素のイベントハンドラが反応しないようにする。 -
return false;
両方止める。
細かくは半年前くらいにブログ書いたのでご参照。
http://d.hatena.ne.jp/modified/20120615/1339731561
子要素がたくさんある時に
<ul>
<li>list1</li>
<li>list2</li>
...
<li>list10</li>
</ul>
bind で直接イベントの設定をすると
$('li').on('click', func );
実際には、中でループが回って一つずつイベントを設定する
<ul>
<li>list1</li> <!-- <= addEventListener! -->
<li>list2</li> <!-- <= addEventListener! -->
...
<li>list10</li> <!-- <= addEventListener! -->
</ul>
代わりに delegate 機能を使うと
$('ul').on('click', 'li', func );
<ul> <!-- <= addEventListener! -->
<li>list1</li>
<li>list2</li>
...
<li>list10</li>
</ul>
実質のイベントリスナは一つなので効率が良く、速度が上がるらしい。
- $(document).on('click', ...) というコードを見たら .live の事。
- delegete が必要になるほどのチューニングと言われても。。
要素の追加/削除はするが、live の使い過ぎが気になったとき?
<div id="parent">
parent
<div id="child">
child
</div>
</div>
<script>
$('#parent').bind('click', function (event){
console.log('parent clicked!');
return false;
});
$('#child').live('click', function (event){
console.log('child clicked!');
return false;
});
</script>
parent は反応するが、child は反応しない。