jQueryで .live() と .bind() を併用する場合の注意
jQuery の .live() メソッドでイベントハンドラを設定した場合、.bind() メソッドで設定したイベントハンドラより後に実行される。以下、検証と詳細。
1. 検証スクリプト
以下、検証用のソース。
<!DOCTYPE html> <html lang="ja"> <head> <title>jQuery .live and .bind</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script> $(function(){ $('*').bind('click', function(){ $('pre').append('bind: ' + this.tagName + '\n'); }); $('a').live('click', function(){ $('pre').append('live: ' + this.tagName + '\n'); }); }); </script> </head> <body> <div><a href="#">[click!]</a></div> <pre></pre> </body> </html>
2. 実行結果
検証用のHTML上で[click!]の部分(a 要素)をクリックすると次のように出力される。環境は Windows 7 + Firefox 3.6。
bind: A bind: DIV bind: BODY bind: HTML live: A
つまり、bind()でバインドされたイベントのバブリングが全て完了してから、live()でバインドしたイベントが処理されていることになる。
3. 問題点
例えば、同じHTMLで次のようにイベントを設定した場合を考える。
$('body').bind('click', function(){ alert('Hello World!!'); }); $('div').bind('click', function(event){ event.stopPropagation(); }); $('a').live('click', function(){ alert('Hello jQuery!!'); });
期待する動作は
- a 要素の click イベント処理(「Hello jQuery!!」のアラート)
- div 要素の click イベント処理 (イベントのバブリング停止)
- body 要素の click イベントは発生しない。
だが、実際には
- div 要素の click イベント処理 (イベントのバブリング停止)
- body 要素の click イベントは発生しない。
- a 要素の click イベントは発生しない。
となる。その結果、期待する a 要素のイベントが発生せずにハマることになる。実際、数十分がこれで消費された……。