イベントは常に JavaScript で最も強力なオブジェクトの 1 つです。 JavaScript には、イベントを DOM ノードにバインドするための 2 つのメソッド、addEventListener とattachEvent が用意されています。jquery はイベントをさらにカプセル化し、さまざまなブラウザと互換性のあるバインド メソッドを提供します。さて、この従来のイベント バインディング方法には次の欠点があります。
1. 多くの EventHander をバインドする必要がある場合があります。
ページ上のテーブルに 100 行がある場合、クリック イベントを各行にバインドする必要があります。その場合、100 個の EventHandler をバインドする必要があり、これらのハンドラーを保存するためにより多くのメモリを作成する必要があるため、ページのパフォーマンスに大きな負担がかかります。
2. DOM ノードにバインドした後はイベントを追加できません。
ページ上のコードが次の場合:
次のようにコードをコピーします。
$("#dv").bind('click',function(){alert('test');});
$(body).append('<div id="dv">テスト</div>')
後で追加した div はクリック イベントをトリガーできません。
これら 2 つの問題を解決するために、JavaScript ではイベント プロキシ (イベント プロキシ) が導入されました。まずはjsにおけるバブリングの仕組みを理解しましょう。
基本的にすべてのブラウザはイベント バブリングをサポートしています。 DOM ノードでイベントがトリガーされると、イベントはドキュメントのルート ノードまで伝播されます。すべてのノード イベントは最終的にドキュメント ルート ノードに配信されるため、イベントをドキュメント ルート ノード (ドキュメント ノード) に直接バインドし、event.target を使用してどのノードがイベントをトリガーしたかを判断すると、大幅にコストが削減されます。 EventHandler についてはどうでしょうか?
jquery の live メソッドは、この原則に基づいて正式に実装されています。 live の単純なバージョンを実装してみましょう。
次のようにコードをコピーします。
$.fn.mylive=function(eventType,fn){
var that=this.selector;
$(document).bind(eventType,function(event){
var match=$(event.target).closest(that)
if(match.length !== 0){
fn.apply($(event.target),[event]);
}
})
}
$("#tb td").mylive('click',function(event){
アラート(event.target.innerHTML);
});
var tb='<テーブル id="tb"> /
<tr> /
<td>最初の列</td>/
<td>2 番目の列</td>/
<td>3 列目</td>/
</tr>/
</テーブル>';
$("本体").append(tb);
ライブ メソッドでは、イベントはドキュメント ノードにバインドされており、$(event.target).closest(that) は実際にイベントをトリガーした要素と一致します。デモでは、後で追加した各 TD にクリック イベントをバインドしました。別の TD をクリックすると、対応するテキスト プロンプト ボックスがポップアップすることがわかります。
ライブ方式は、前述した従来のイベント バインディング方式の 2 つの欠点を補います。しかし、ライブ方式にはまだ欠点があります。このコードを見てください:
次のようにコードをコピーします。
$("#tb td").mylive('click',function(event){
アラート(event.target.innerHTML);
});
まず、jquery セレクターに基づいてドキュメント全体を走査し、すべての #tb td 要素を見つけて、それらをオブジェクトとして保存します。ただし、ライブ実装方法ではこれらのオブジェクトは使用せず、イベントソースと照合する文字列として「#td td」のみを使用します。これにより、不必要な消費が大幅に増加します。
では、この状況を改善する方法はあるのでしょうか?デリゲート プロキシ メソッドは jQuery で提供されており、ドキュメントだけでなく指定された要素へのイベントのバインドをサポートします。その原理を理解した上で、単純なバージョンのデリゲートを実装してみましょう。
次のようにコードをコピーします。
$(body).append('<div id="dv"></div>');
$.fn.mydelegate=function(selector,eventType,fn){
$(this).bind(eventType,function(event){
var match=$(event.target).closest(selector);
if(match.length !== 0){
fn.apply($(event.target),[event]);
}
});
}
$("#dv").mydelegate('td','click',function(event){
アラート(event.target.innerHTML);
});
var tb='<テーブル id="tb"> /
<tr> /
<td>最初の列</td>/
<td>2 番目の列</td>/
<td>3 列目</td>/
</tr>/
</テーブル>';
$("dv").append(tb);
mydeletage メソッドはすべての td オブジェクトを取得する必要はありませんが、イベントがバインドされている div オブジェクトのみを取得する必要があります。実行効率の点では、ライブ方式よりも優れています。
これは、イベント プロキシの原理を誰もが理解できるようにするための単なる紹介です。jquery での live と delegate の実装はさらに複雑です。