動的HTMLをロードした後にクリックイベントを追加するためのjQuery .live()メソッドと.on()メソッド


216

私は.live()メソッドが明らかに非推奨であるjQuery v.1.7.1を使用しています。

私が抱えている問題は、次のように使用して要素にHTMLを動的にロードする場合です。

$('#parent').load("http://..."); 

後でクリックイベントを追加しようとしても、これらの方法のいずれかを使用してイベントが登録されません。

$('#parent').click(function() ...); 

または

// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...); 

この機能を実現する正しい方法は何ですか?それは私にとって.live()でのみ機能するようですが、私はそのメソッドを使用するべきではありません。#childは動的にロードされる要素であることに注意してください。

ありがとう。


25
なぜ「おそらく非推奨」と言うのですか?あなたはドキュメントを信じませんか?

6
それはないですおそらく非推奨:それがされる非推奨します。jQuery doco.live()を見ると、既存の使用方法.live()を使用.delegate()またはに変更する方法がわかります.on()(バージョン1.7+ を使用しているかどうかによって異なります)。ただし、.click()「後で」というようにハンドラーを追加した場合、つまり要素を動的にロードした後は機能するはずです-唯一の問題は、要素を動的にロードする.click() にで割り当てようとすることです。
nnnnnn 2012年

基本的に私が言っていたので、表現を「明らかに」に変更しました。とにかく、.load()イベントは非同期であるため、#child要素は成功ハンドラーで確実にしか認識されなかったことがわかりました。これは理にかなっています。
Sean Thoman、2012年

回答:


606

動的に読み込まれる要素に対してクリックハンドラーを機能させるには、(動的に読み込まれない)親オブジェクトにイベントハンドラーを設定し、動的オブジェクトに一致するセレクターを次のように指定します。

$('#parent').on("click", "#child", function() {});

イベントハンドラーは#parentオブジェクトにアタッチされ#child、で発生したクリックイベントがそのオブジェクトにバブルアップするたびに、クリックハンドラーを起動します。これは、委任イベント処理と呼ばれます(イベント処理は親オブジェクトに委任されます)。

イベントをにアタッチできるため、この方法で行われます #parent場合でも、対象#childのオブジェクトがまだ存在していませんが、それは後で存在し、クリック取得したときにクリックイベントの意志バブルアップ#parentオブジェクトは、それが上の発祥ことがわかります#childし、クリックし#childてイベントを発生させるイベントハンドラがあります。


23
素晴らしい説明!私は前のまわりで私の頭をラップすることができていたことがありませんlive()on()けど、今夜は私はまだもう一度試してみることにし、あなたの説明はすぐに私はすべてを一緒に行方不明になっていたものを明らかにしました。ありがとう!
MikeSchinkel 2013年

6
100万の上昇。動的に作成された子のjQueryでこれが可能であることに気づく前に、ノックアウトを使い始めました。どうもありがとうございました。
Brock Hensley 2013

9
本や何かを書くことを検討する必要があります。あなたの小さなテキストは、« on() » についてのjQueryドキュメントの全ページよりも私にとってより役に立ちました。どうもありがとう!
コレステロール

@ jfriend00ホバー、非ホバーの状況にこれと同じプロセスを適用する方法を知っていますか?これについて話すソースはありますか?
クレウィス2016年

@blackhawk- この回答を参照してください。mouseentermouseleaveイベントに登録し、トリガーされたハンドラー内でテストできます。jQueryの疑似「ホバー」イベントは、委任では使用できません。
jfriend00

33

これを試して:

$('#parent').on('click', '#child', function() {
    // Code
});

$.on()ドキュメントから:

イベントハンドラーは、現在選択されている要素にのみバインドされます。これらは、コードがを呼び出すときにページ上に存在している必要があります.on()

あなたの#childお電話の際は、要素が存在しない$.on()イベントが(とは異なり、バインドされていないので、その上で$.live())。#parentただし、存在するため、イベントをそれにバインドすることは問題ありません。

上記のコードの2番目の引数は、イベントが#parentfromにバブリングした場合にのみトリガーする「フィルター」として機能し#childます。


$ .load()メソッドの後に$ .on()メソッドを呼び出すと、その時点で#child要素が存在しないのはなぜですか?
Sean Thoman、2012年

6
@SeanThoman- メソッドの.load()後のコードからではなく、メソッドの成功ハンドラから呼び出す必要があります.load()#childロードされるのは、成功ハンドラが実際に実行されたときだけであり、前に読み込まれることはありません。
jfriend00

それでも、取得したデータをDOMに挿入するのにかかる時間は、接続できない可能性があることを意味します。私は最近、多くの単一ページアプリの作業を行っており、私の標準はvar $ body = $( 'body');です。$ body.on( "event"、 ".element /#class"、function(e){}); 全てにおいて。1セレクタ。何がロードされているか、何がロードされていないかについての心配はありません。
lupos 2013

21

$(document).on('click', '.selector', function() { /* do stuff */ });

編集:私はこれがどのように機能するかについてもう少し情報を提供しています、なぜなら...言葉だからです。この例では、ドキュメント全体にリスナーを配置しています。

click一致する要素を使用する.selectorと、イベントが親ドキュメントevent.stopPropagation()にバブリングされる、メソッドを呼び出すリスナーが他にない限り、イベントがメインドキュメントにバブリングします。

特定の要素または要素のセットにバインドする代わりに、指定したセレクターに一致する要素からのイベントをリッスンしています。つまり、現在存在する要素や動的に追加された要素に自動的に一致するリスナーを1回だけ作成できます。

これは、パフォーマンスやメモリ使用率(大規模アプリケーションで)を含むいくつかの理由で賢いです

編集:

言うまでもなく、リッスンできる最も近い親要素の方が優れdocumentています。イベントを監視する子がその親要素内にある限り、代わりに任意の要素を使用できますが、実際には何もする必要はありません。質問で。


23
彼は試した$(element).on(...)。これです$(document).on(...,element,...)。別の獣。
cHao

@ArnoldRoaはい、パフォーマンスが向上します。複数の子にリスナーを配置したり、DOMが変更されるたびにリスナーを再適用したりする必要はありません。デフォルトでは、イベントはDOMを介してバブルアップします。1回実行すると、セレクターに一致するすべての子がクリックされると、指定された関数がトリガーされます。
L422Y

@ L422Yのコメントは誤解を招く可能性があります。あなたはパフォーマンスへの影響について興味があれば、見とる@ jfriend00さんのコメントジャレッドの答え@
ガストファンデウォルマート

@GustvandeWalそれはどのように誤解を招くのですか?親要素でイベントを1回リッスンするのと比較して100 $(this).on(...)を発行すると、パフォーマンスが大幅に向上します。
L422Y

あなたはイベントを添付することについて話しているだけです。実際のパフォーマンスのボトルネックは、(あなたが委任するリスナーのように)起動するリスナーが多すぎて、イベントをアタッチする必要のある大量の要素ではありません。
Gust van de Wal

12

1.7の.live()に相当するものは次のようになります。

$(document).on('click', '#child', function() ...); 

基本的に、ドキュメントでクリックイベントを監視し、#childでフィルタリングします。


それは、イベントハンドラーがドキュメントにアタッチする方法だからです(方法.live()はそうです)。
cHao、2012年

17
.live()現在非推奨となっている理由の1つは、すべてのライブイベントハンドラーをドキュメントオブジェクトに配置することが不適切であるためです。物事は本当に、本当に遅くなる可能性があります。イベントはドキュメントに至るまでバブリングする必要があるだけでなく、ドキュメントオブジェクトを調べる多くのイベントハンドラが必要になる場合があります。の主な利点は.on()、実際のオブジェクトに非常に近い親オブジェクトにアタッチして、パフォーマンスを大幅に向上できることです。だから...私は.on()ドキュメントオブジェクトで使用することをお勧めしません。より近い親オブジェクトを選択する方がはるかに優れています。
jfriend00

説明をありがとう。イベントのパフォーマンスはon()で大幅に改善されているため、以前ほど問題にはなりません。親にアタッチする場合は、ドキュメントの準備が整っている親である必要があるか、または同様の問題が発生すると思います。
Jared

最悪の場合、これ非推奨の.live()アプローチをエミュレートします。ただし、委任を制御する機能は確かに有利です。
Dan Lugg、2013年

9

答えが少し遅いのはわかっていますが、.live()メソッド用のポリフィルを作成しました。私はjQuery 1.11でテストしましたが、かなりうまく機能しているようです。可能な限り.on()メソッドを実装することになっていることはわかっていますが、何らかの理由ですべての.live()呼び出しを同等の.on()呼び出しに変換することができない大きなプロジェクトでは、次のようになります。作業:

if(jQuery && !jQuery.fn.live) {
    jQuery.fn.live = function(evt, func) {
        $('body').on(evt, this.selector, func);
    }
}

jQueryをロードした後、live()を呼び出す前に、それを含めるだけです。


5

.on()は、jQueryバージョン1.7以降用です。古いバージョンを使用している場合は、これを使用してください:

$("#SomeId").live("click",function(){
    //do stuff;
});

8
OPによると、「私はjQuery v.1.7.1を使用しています」
Selvakumar Arumugam

1
@ jfriend--私の投票に投票するのではなく、自分の回答を投稿してみませんか?私は毎日1.6()未満のすべてのバージョンでlive()を使用しており、正常に動作します。あなたはドキュメンテーションを読むのが得意だと思いますが、人のために何かを実践する方が役立つ場合もあります。.live()は機能します。限目。
Matt Cashatt、2012年

5
@MatthewPatrickCashatt-私は自分の回答を投稿し、あなたの回答に反対票を投じませんでした-そのような盲目的な仮定をしないでください。1.7 .delegate()より前のバージョンでは.live()、jQueryドキュメントで推奨されているため、パフォーマンスが大幅に向上してい.live()ます。はい、.live()まだ機能しますが、ここでのSOの答えは、より良い方法を推奨するはずです。これをここで20回見ました。.live()ここでSOを使用してコードを投稿すると、そのコードは反対票を投じます(他に深刻な問題がない限り、通常は私によって投票されません)。
jfriend00

1
私はdownvoteませんでしたが、けれども.live()確かにもバージョン1.7にあなたはまだ使用すべき作品.delegate().on()理由が.live()正当な理由のために廃止されました。2つの新しい関数の構文の変更に注意すれば、どちらでも問題なく機能します。
nnnnnn 2012年

1
@ jfriend00-あなたは絶対に正しいです。長い一日。謝罪いたします。
Matt Cashatt、2012年

3

プロジェクトで「ライブ」を使用しましたが、私の友人の1人が、ライブではなく「オン」を使用するように提案しました。そして、それを使おうとしたときに、あなたが経験したような問題が発生しました。

私のページでは、ボタンテーブルの行と多くのDOMを動的に作成します。でも魔法を使うと消えてしまいました。

子供のように使用するなどの他のソリューションは、クリックするたびに関数を呼び出すだけです。しかし、私はそれを再び起こす方法を見つけました、そしてここに解決策があります。

コードを次のように記述します。

function caller(){
    $('.ObjectYouWntToCall').on("click", function() {...magic...});
}

caller();を呼び出します。このようなページでオブジェクトを作成した後。

$('<dom class="ObjectYouWntToCall">bla... bla...<dom>').appendTo("#whereeveryouwant");
caller();

このようにして、ページ上のすべてのクリックではないことになっているときに、関数が呼び出されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.