Dinamik html yüklendikten sonra bir tıklama etkinliği eklemek için jQuery .live () vs .on () yöntemi


217

.Live () yöntemi görünüşte kullanımdan kaldırılmıştır jQuery v.1.7.1 kullanıyorum.

Ben yaşıyorum sorun dinamik olarak kullanarak bir öğeye html yüklerken:

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

Ben denemek ve daha sonra bir click olayı eklemek, bu yöntemlerden birini kullanarak olay kaydetmez:

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

veya

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

Bu işlevselliği elde etmenin doğru yolu nedir? Benim için sadece .live () ile çalışıyor gibi görünüyor, ama bu yöntemi kullanmamalıyım. #Child'in dinamik olarak yüklenen bir öğe olduğunu unutmayın.

Teşekkürler.


25
Neden "sözde reddedildi" diyorsunuz? Belgelere inanmıyor musunuz?

6
O değil sözde kaldırılan: Bu edilir kullanımdan kaldırıldı. Bunun için jQuery doco'ya.live() bakarsanız, .live()kullanımın mevcut kullanımlarını nasıl yeniden yazacağınızı .delegate()veya .on()(1.7 ve sonraki sürümde olup olmadığınıza bağlı olarak) anlatır . Ancak, .click()daha sonra bahsettiğiniz gibi "sonradan" olan bir işleyici eklerseniz , yani öğeleri dinamik olarak yükledikten sonra, işe yarayacağını unutmayın - tek sorun, öğeleri dinamik olarak yüklemeden .click() önce atamaya çalışmaktır .
nnnnnn

İfadeyi 'görünüşte' olarak değiştirdim çünkü temelde kastettiğim buydu. Her neyse, şimdi anlıyorum ki .load () olayı eşzamansız olduğundan #child öğesi sadece başarı işleyicisinde güvenilir bir şekilde tanınabilir, bu da mantıklı.
Sean Thoman

Yanıtlar:


606

Tıklama işleyicisinin dinamik olarak yüklenen bir öğe için çalışmasını istiyorsanız, olay işleyicisini bir üst nesneye (dinamik olarak yüklenmeyen) ayarlarsınız ve bu öğeye dinamik nesnenizle eşleşen bir seçici verirsiniz:

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

Olay işleyicisi #parentnesneye eklenir ve bir tıklama olayı, kaynak oluşturulduğunda tıklandığında her zaman #childtıklama işleyicinizi tetikler. Buna yetkilendirilmiş olay işleme adı verilir (olay işleme, bir üst nesneye devredilir).

Bu şekilde yapılır, çünkü nesne henüz mevcut olmasa #parentbile nesneye ekleyebilirsiniz #child, ancak daha sonra var olduğunda ve tıklandığında, click olayı #parentnesneye yayılır, nesnenin kaynaklandığını #childve bir tıklama #childve etkinliğinizi tetiklemek için bir olay işleyici vardır .


23
Harika bir açıklama! Daha önce kafamı sarmak için başaramadım live()vs. on()ama bu gece yine denemeye karar verdi ve senin açıklaman hemen Baştan beri kayıp olmuştu neyi ortaya çıkardı. Teşekkürler!
MikeSchinkel

6
Bir milyon iniş . Bu dinamik olarak oluşturulan çocuklar için jQuery mümkün olduğunu fark etmeden nakavt kullanmaya başladım, çok teşekkür ederim.
Brock Hensley

9
Bir kitap veya başka bir şey yazmayı düşünmelisiniz: küçük metniniz benim için jQuery belgelerindeki « on () » hakkındaki tam sayfadan daha yararlı oldu . Çok teşekkürler!
Kolesterol

@ jfriend00 Aynı işlemi vurgulu ve vurgulu olmayan bir duruma nasıl uygulayabileceğimizi biliyor musunuz? bunun hakkında konuşan bir kaynak var mı?
klewis

@blackhawk - Bu cevaba bakınız . mouseenterVe mouseleaveolaylarına kaydolabilir ve hangisinin tetiklendiğini işleyicinin içinde test edebilirsiniz. jQuery'nin sözde "hover" etkinliği temsilci ile kullanılamaz.
jfriend00

33

Bunu dene:

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

Gönderen $.on()belgeler:

Olay işleyicileri yalnızca seçili öğelere bağlıdır; kodunuzun çağrıldığı sırada sayfada bulunmaları gerekir .on().

Sizin #childAradığınızda eleman yok $.on()olay (aksine bağlı değildir, bu yüzden, üzerinde $.live()). #parentancak, bu nedenle, olayı buna bağlamak iyidir.

Sadece tetikleyici bir 'filtre' eylemlerine yukarıda benim kodunda ikinci argüman olay için köpürdü eğer #parentgelen #child.


$ .Load () yönteminden sonra $ .on () yöntemini çağırırsam, neden #child öğesi bu noktada mevcut olmaz?
Sean Thoman

6
@SeanThoman - .load()yöntemden sonraki koddan değil , yöntemin başarı işleyicisinden çağırmanız gerekir .load(). #childyalnızca başarı işleyicisinin daha önce değil, gerçekten yürütüldüğünde yüklendiği bilinmektedir.
jfriend00

ve hatta DOM'a geri aldığınız verileri eklemek için geçen süre, bağlanmayabileceği anlamına gelir. Son zamanlarda tek bir sayfa uygulaması çalışması yapıyorum ve benim standart var $ body = $ ('body'); $ body.on ("etkinlik", ".element / # class", işlev (e) {}); herşey için. 1 seçici. Neyin yüklü olup olmadığı konusunda endişelenmenize gerek yok.
Lupos

21

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

EDIT: Bunun nasıl çalıştığı hakkında biraz daha bilgi veriyorum, çünkü ... kelimeler. Bu örnekle, belgenin tamamına bir dinleyici yerleştiriyorsunuz.

Ne zaman clickherhangi bir eleman (lar) eşleştirmeye .selector, olay ana belgeye kadar kabarcıklar - çok uzun başka dinleyici olarak orada o çağrı event.stopPropagation()yöntemi - ebeveyn elemanlarına bir olayın baloncuklanmasını top olacaktır.

Belirli bir öğeye veya bir dizi öğeye bağlanmak yerine, belirtilen seçiciyle eşleşen öğelerden gelen olayları dinliyorsunuz. Bu, mevcut olarak mevcut öğelerle ve dinamik olarak eklenen tüm öğelerle otomatik olarak eşleşecek bir kez bir dinleyici oluşturabileceğiniz anlamına gelir.

Performans ve bellek kullanımı da dahil olmak üzere birkaç nedenden dolayı akıllıdır (büyük ölçekli uygulamalarda)

DÜZENLE:

Açıkçası, dinleyebileceğiniz en yakın üst öğe daha iyidir ve documentolayları izlemek istediğiniz çocuklar o ana öğenin içinde olduğu sürece herhangi bir öğeyi kullanabilirsiniz ... soru ile.


23
Denedi $(element).on(...). Bu $(document).on(...,element,...). Farklı hayvanlar.
cHao

@ArnoldRoa evet, daha iyi performans. birden fazla çocukta dinleyiciniz olmayacak, DOM her değiştirildiğinde dinleyiciyi yeniden uygulamak zorunda kalmayacaksınız ve etkinlikler varsayılan olarak DOM'da gerçekleşiyor. Bir kez çalıştırın ve seçiciyle eşleşen her alt öğe tıklatıldığında verilen işlevi tetikler.
L422Y

@ L422Y'nin buradaki yorumu çok yanıltıcı. Performans etkileri hakkında şüpheleriniz varsa, bir göz atın @ jfriend00 yorumuna üzerinde Jared'in cevap @
Gust van de Wal

@GustvandeWal Nasıl yanıltıcı? Gitmek ve bir üst öğede bir kez bir olay dinlemek için yüz $ (this) .on (...) vs verirseniz, bu daha fazla performans gösterir.
L422Y

Sadece olayları eklemekten bahsediyorsun. Gerçek dünyadaki performans darboğazları, kendilerine eklenmiş bir etkinliğe ihtiyaç duyan çok miktarda öğe değil, çok fazla dinleyici işliyor (temsilci atadığınız kişiler gibi).
Gust van de Wal

12

1.7'deki .live () eşdeğeri şuna benzer:

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

Temel olarak, tıklama etkinlikleri için belgeyi izleyin ve # çocuk için filtreleyin.


Çünkü olay işleyici belgeye bu şekilde eklenir (yol .live()böyle).
cHao

17
.live()Şimdi kullanımdan kaldırılmasının bir nedeni, tüm canlı etkinlik işleyicilerini belge nesnesine koymanın kötü olmasıdır. İşler gerçekten, gerçekten yavaşlayabilir. Olayların yalnızca belgeye kadar dolması gerekmez, aynı zamanda belge nesnesine bakmak için çok sayıda olay işleyiciniz olabilir. Başlıca avantajı, .on()onu gerçek nesneye çok daha yakın olan bir üst nesneye ekleyebilmeniz ve performansı önemli ölçüde artırabilmenizdir. Yani ... .on()Belge nesnesiyle kullanmanızı tavsiye ETMEM . Daha yakın bir ana nesne seçmek çok daha iyi.
jfriend00

Açıklama için teşekkürler. Değer için ne olursa olsun, olayların performansı on () ile çok geliştirildi, bu yüzden eskisinden daha az bir sorun olmalı. Bir ebeveyne ekliyorsanız, belgede hazır olan bir ebeveyni olması gerektiğini ya da benzer sorunları göreceğinizi varsayarım.
Jared

En kötüsü, bu mu kaldırılan taklit .live()yaklaşımı; ancak delegasyonu kontrol etme yeteneği kesinlikle avantajlıdır.
Dan Lugg

9

Yanıt için biraz geç olduğunu biliyorum, ama .live () yöntemi için bir çoklu dolgu oluşturdum. Ben jQuery 1.11 test ettik ve oldukça iyi çalışıyor gibi görünüyor. Mümkün olan yerlerde .on () yöntemini uygulamamız gerektiğini biliyorum, ancak tüm .live () çağrılarını eşdeğer .on () çağrılarına herhangi bir nedenle dönüştürmenin mümkün olmadığı büyük projelerde, aşağıdakiler olabilir iş:

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

Sadece jQuery yükledikten sonra ve live () çağırmadan önce ekleyin.


5

.on (), jQuery 1.7 ve üstü sürümler içindir. Eski bir sürümünüz varsa, bunu kullanın:

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

8
OP "jQuery v.1.7.1 kullanıyorum" diyor
Selvakumar Arumugam

1
@ jfriend - neden benim cevabını düşürmek yerine kendi cevabınızı göndermiyorsunuz? 1.6'dan küçük tüm sürümlerle her gün live () kullanıyorum ve iyi çalışıyor. Belgeleri okuma konusunda iyi olduğunuzu görebiliyorum, ancak bazen bir kişi için bir şeyler uygulamaya koymak daha fazla yardımcı olur. .live () çalışır. Dönemi.
Matt Cashatt

5
@MatthewPatrickCashatt - Kendi cevabımı gönderdim ve sizinkini küçümsemedim - böyle kör varsayımlar yapmaya gitmeyin. Ön 1.7, jQuery dokümanı önerdiğinden ve reddettiği için .delegate()çok daha iyi performans gösterir . Evet, hala çalışıyor, ancak SO'daki cevaplar bir şeyler yapmanın daha iyi bir yolunu tavsiye etmelidir. Bunu burada SO'da 20 kez gördüm. SO ile burada kod gönderirseniz, aşağı indirilecek (bununla ilgili ciddi bir şey olmadığı sürece genellikle benim tarafımdan değil). .live().live().live().live()
jfriend00

1
Ben downvote yoktu, ama her ne kadar .live()kesinlikle bile sürümünde hala kullanmalıdır 1.7 çalışır .delegate()ya .on()çünkü .live()iyi bir neden için kullanımdan kaldırıldı. İki yeni işlev için sözdizimindeki değişikliği not ettiğiniz sürece her ikisi de iyi çalışır.
nnnnnn

1
@ jfriend00- Kesinlikle haklısın. Uzun gün. Özür dilerim.
Matt Cashatt

3

Projemde 'canlı' kullandım ama arkadaşımdan biri canlı yerine 'açık' kullanmamı önerdi. Ve kullanmaya çalıştığımda senin gibi bir sorun yaşadım.

Sayfalarımda dinamik olarak düğmeler tablo satırları ve birçok dom şeyler oluşturuyorum. ama büyü kullandığımda kayboldu.

Bir çocuk gibi kullanmak gibi diğer çözümler, her tıklamada işlevlerinizi çağırır. Ama tekrar yapmanın bir yolunu buluyorum ve işte çözüm.

Kodunuzu şu şekilde yazın:

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

Arayanı çağırın (); nesnenizi sayfada böyle oluşturduktan sonra.

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

Bu şekilde, sayfadaki her bir tıklama olmaması gerektiğinde işleviniz çağrılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.