バージョン1.4.2の発表に対するコメントでは、jQueryの新しいバージョンに登場した2つの新しいメソッドについて多くの質問がありました。
jQuery 1.4.2には、.delegate()と.undelegete()という2つの新しいメソッドが追加されたことを聞いたことがあるでしょう。 これらの2つのメソッドは、それぞれ.live()および.die()メソッドと同じ目的で使用され、異なる構文のみを使用します。
初心者向け:.live()は、ドキュメント内の要素にイベントをバインドできるjQueryのメソッドであり、将来登場する要素と同じくらい簡単です。 たとえば、.live()を介してイベントをバインドします。
$( 'img.photo' ).live( 'click' , function (){
lightboxify( this );
});
次に、AJAX経由でいくつかの写真を追加します。
// append an image
$( 'body' ).append( '<img src="face.jpg" alt="silly face" class="photo"/>' );
click()イベントは新しい画像にバインドされます。 新しいイベントバインディングの必要はありません。 便利ですか?
少し前まで、.live()メソッドについていくつかの 議論がありました(jQueryフォーラムとpaulirish.comへの翻訳されたリンクに注意してください )。 議論された問題の1つは、.live()メソッドを呼び出しのチェーンで(トラバーサルと一緒に)使用しようとするとエラーがスローされることでした。 例:
// FAILS
$( 'ul' ).find( 'li' ).next().live( 'click' , function (){});
// FAILS
$( 'ul' ).parent().nextAll().live( 'click' , function (){});
また、通常のDOM要素にバインドする場合でも、エラーが発生します。
// FAILS
$( document .body).live( 'click' , function (){});
残念ながら、.live()を使用する場合は、チェーンの「上」にある必要があります。
// WORKS
$( 'ul li' ).live( 'click' , function (){})
これは、jQueryが提供するトラバースと呼び出しチェーンを使用する多くの人々にとって混乱を招く可能性があるため、.live()メソッドの構文の議論になりました。 なぜ、他の方法のように見えるのに、異なる振る舞いをするのですか? その結果、これはコードの基本的な改訂に反映され、開発者は.live()および.die()に加えて.delegate()および.undelegate()を導入することにしました。
.live()および.die()の一般的な使用例と、.delegate()および.undelegate()の使用方法の例を次に示します。
古い方法:
// Using .live()
$( "table" ).each( function (){
$( "td" , this ).live( "hover" , function (){
$( this ).toggleClass( "hover" );
});
});
// Using .die()
$( "table" ).each( function (){
$( "td" , this ).die( "hover" );
});
新しい方法:
// Using .delegate()
$( "table" ). delegate ( "td" , "hover" , function (){
$( this ).toggleClass( "hover" );
});
// Using .undelegate()
$( "table" ).undelegate( "td" , "hover" );
.delegate()メソッドの利点は、コンテキストを定義できることです。 これにより、目的の要素に到達するためにDOM構造全体を確認する必要がなくなります。 .live()メソッドは、コンテキストを何らかの方法で次のように定義しない限り、毎回DOM構造体を通過します。
$( 'td' , $( 'table' )[0]).live( 'hover' , function (){})
ひどいですね!
デリゲート()はbind()メソッドに似ていると考える人もいます。 以下に示すように、構文はわずかに異なります
// .bind() way
$( 'ul li' ).bind( 'click' , function (e){
// Do something with bind
});
// .delegate() way
$( 'ul' ). delegate ( 'li' , 'click' , function (e){
// Do something with delegate
});
つまり、.bind()と.delegate()の違いは、.bind()がページ上の要素にイベントを追加するだけであるということです。 .delegate()は、新しい要素の外観を追跡し、発生時にイベントを追加します。
.delegate()メソッドのバグ
.delegate()は、.bind()とは異なり、イベントの配列(イベントのオブジェクトマップ )を処理できません。 .bind()を使用した例:
// This works wonderfully
$( 'ul li' ).bind({
click: function (e){
// Something on click
},
mouseover: function (e){
// Something on mouse over
}
});
以下を実行しようとするとエラーが発生します。
// FAILS!
$( 'ul' ). delegate ( 'li' , {
click: function (e){
// Something on click
},
mouseover: function (e){
// Something on mouse over
}
});
この理由は定かではありませんが、これを反省するのは私だけではないと思います。
ところで、.bind()にはjQuer 1.4より前のこの機能はありませんでした。 .live()と.delegate()で同じメソッドを使用することにした場合、Robert Katitzは、自分で組み込むことができる小さなコードを作成しました。 ここに持っていってください 。
上記のRobert Katitzパッチの使用をお勧めしますが、もちろん他の方法もあります。 たとえば、独自の変更されたオブジェクトマップを作成できます。
var customObjMap = {
click : function (e){
// Something on click
},
mouseover : function (e){
// Something on mouse over
}
};
$( 'ol' ). delegate ( 'li' , 'click mouseover' , function (e){
if ($.isFunction(customObjMap[e.type])){
customObjMap[e.type].call( this , e);
}
});
* This source code was highlighted with Source Code Highlighter .
.delegate()および.live()メソッドのもう1つのバグは、mouseenterおよびmouseleaveイベントを要素に追加し、コールバック関数でそのタイプ(e.type)をチェックすると、マウスオーバーおよびマウスアウトとして正しく表示されないことです。 一方、.bind()は、予想どおり、mouseenterとmouseleaveを示します。 以下に例を示します。
$( 'ol' ). delegate ( 'li' , 'mouseenter' , function (e){
alert(e.type); // outputs mouseover
});
$( 'ol li' ).bind( 'mouseenter' , function (e){
alert(e.type); // outputs mouseenter
});
更新:このバグは修正されており、jQueryの新しいバージョンではすべて問題ありません。
一般に、バグは.delegate()および.undelegte()メソッドが提供する利点を減じません。 実際、jQueryコアへの優れた追加機能です。