jQuery は、イベントをバインドおよび委任するための .bind()、.live()、および .delegate() メソッドを提供します。この記事では、これらのメソッドの内部実装について説明し、その利点、欠点、および適用可能な状況を示します。
イベント委任
イベント委任の例は現実にたくさんあります。たとえば、3 人の同僚が月曜日に速達便を受け取る予定だとします。速達の署名方法は 2 つあります。1 つは会社の玄関で 3 人で速達を待ってもらう方法、もう 1 つは受付担当者に代理で署名を依頼する方法です。実際には、私たちは主に委託ソリューションを使用しています (会社は、速達を待っているだけでドアに立っている多くの従業員を容認しません)。フロントデスクの MM は速達便を受け取ると、受取人が誰であるかを判断し、受取人の要件に従って署名し、代わりに代金を支払います。このソリューションのもう 1 つの利点は、新入社員が (人数に関係なく) 会社に来ても、フロント デスクの MM が新入社員に送られた速達便を確認し、新入社員に代わって署名することです。
DOM がページ内の各要素にイベントをディスパッチすると、通常、対応する要素がイベント バブリング ステージでイベントを処理することがわかっています。 body > div > a のような構造では、a 要素をクリックすると、クリック イベントが a から div と body (つまりドキュメント オブジェクト) に発生します。したがって、a、div、body 要素で発生するクリック イベントも処理できます。イベント伝播のメカニズム (ここではバブリング) を使用することで、イベントの委任を実現できます。具体的には、イベント委任とは、イベント ターゲットがイベント自体を処理するのではなく、処理タスクをその親要素や祖先要素、さらにはルート要素 (ドキュメント) に委任することを意味します。
.bind()
複数の行と列を含むテーブルがあるとします。ユーザーが各セルをクリックすると、その内容に関連する詳細情報が表示されます。情報(ツールチップなどを介して)。これを行うには、クリック イベントを各セルにバインドします。
$("info_table td").bind("click", function(){/*詳細情報を表示*/}); >
問題は、クリック イベントがバインドされているテーブルに 10 列と 500 行がある場合、5000 個のセルを検索して走査すると、スクリプトの実行が大幅に遅くなる一方で、5000 個の td 要素と対応するイベントが保存されることです。ハンドラーも多くのメモリを消費します (全員が物理的にドアの前に立って配達を待っているのと同じです)。
前の例に基づいて、単純なフォト アルバム アプリケーションを実装する場合、各ページには 50 枚の写真 (50 セル) のサムネイルのみが表示され、ユーザーは「ページ x」(または「次のページ」) をクリックします。 ) リンクは、Ajax 経由でサーバーからさらに 50 枚の写真を動的にロードできます。この場合、 .bind() メソッドを使用した 50 個のセルのバインディング イベントが再び受け入れられるようです。
そうではありません。 .bind() メソッドを使用すると、クリック イベントは最初のページの 50 個のセルにのみバインドされ、動的に読み込まれる後続のページのセルにはこのクリック イベントがありません。つまり、 .bind() は、呼び出されたときにすでに存在する要素にイベントをバインドすることしかできず、将来追加される要素にイベントをバインドすることはできません (新入社員が速達配送を受け取ることができないのと同様)。
イベント委任は、上記の 2 つの問題を解決できます。コード固有の場合は、.bind() メソッドの代わりに jQuery 1.3 で追加された .live() メソッドを使用します:
$("#info_table td").live("click",function() {/*詳細情報を表示*/});
ここでの .live() メソッドは、クリック イベントを $(document) オブジェクトにバインドします (ただし、これはコードから反映できません。これも.live() メソッドが批判されている重要な理由 (後で詳しく説明します)、$(document) を 1 回バインドするだけで済みます (50 回どころか、5000 回も)。その後は、その後の動的処理を行うことができます。フォトセルのクリックイベント。イベントを受信すると、$(document) オブジェクトはイベント タイプとイベント ターゲットを確認し、それがクリック イベントでイベント ターゲットが td の場合、それに委任されたハンドラーが実行されます。
.live()
これまでのところ、すべてが完璧であるようです。残念ながらそうではありません。 .live() メソッドは完璧ではないため、次のような大きな欠点があります。
$() 関数は現在のページ内のすべての td 要素を検索し、jQuery オブジェクトを作成しますが、確認時には使用されません。イベント ターゲット。この td 要素のコレクションは代わりにセレクター式を使用して、event.target またはその祖先要素と比較します。そのため、この jQuery オブジェクトを生成すると、不要なオーバーヘッドが発生します。
イベントはデフォルトで $(document) 要素にバインドされます。 DOM の入れ子構造が非常に深い場合、多数の祖先要素を介したイベントのバブリングによりパフォーマンスの低下が発生します。
は直接選択された要素の後にのみ配置でき、連続した DOM トラバーサル メソッドの後には使用できません。 、$("#infotable td ").live... は機能しますが、$("#infotable").find("td").live... は機能しません。
は td 要素を収集し、jQuery オブジェクトを作成します。ですが、実際の操作は $( document) オブジェクトであり、不可解です。
解決策
不要な jQuery オブジェクトの生成を避けるために、$(document).ready ( ) メソッド外部呼び出し .live():
PS: According to the release notes of jQuery 1.7 Beta 1, in order to solve the inconsistency problem caused by the coexistence of .bind(), .live() and .delegate(), jQuery 1.7 will add a For new event methods: .on() and .off():
$(elems).on(events, selector, data, fn);
$(elems).off(events, selector, fn) );
If selector is specified, it is event delegation; otherwise, it is regular binding. The correspondence between the old and new APIs is as follows:
(Note: This article is compiled based on the relevant chapters of "JQuery Basics Tutorial (3rd Edition)", and also refers to