Doğrudan ve Yetki Verilmiş - jQuery .on ()


159

JQuery .on () yöntemini kullanarak doğrudan ve yetki verilen olay işleyicileri arasındaki bu özel farkı anlamaya çalışıyorum . Özellikle, bu paragraftaki son cümle:

A selectorsağlandığında, olay işleyiciye yetki verilmiş olarak adlandırılır . Olay doğrudan bağlı öğede gerçekleştiğinde işleyici çağrılmaz, yalnızca seçiciyle eşleşen torunlar (iç öğeler) için çağrılır. jQuery olayı olay hedefinden, işleyicinin bağlı olduğu öğeye (yani, en içteki en dış öğeye) kadar kabarcıklı hale getirir ve seçiciyle eşleşen bu yol boyunca herhangi bir öğe için işleyiciyi çalıştırır.

"Herhangi bir eleman için işleyiciyi çalıştırır" ne anlama gelir? Kavramı denemek için bir test sayfası yaptım . Ancak aşağıdaki yapıların her ikisi de aynı davranışa yol açar:

$("div#target span.green").on("click", function() {
   alert($(this).attr("class") + " is clicked");
});

veya,

$("div#target").on("click", "span.green", function() {
   alert($(this).attr("class") + " is clicked");
});

Belki birisi bu noktayı açıklığa kavuşturmak için farklı bir örneğe başvurabilir? Teşekkürler.


7
dgo

1
@KevinWheeler Aşağıdaki kemanınız hakkında yorum yaptım, ancak burada , aslında doğru bir şekilde kurulmadı (ana öğeye bağlanıyorsunuz ve temsilci seçme çocuklara yöneliktir). Sorunuzu cevaplamak için, temsilci işleyicinin temsilci olmayan yeni öğelerin eşleşeceği anlamına gelir. Temsilci seçme, uygulama için daha az bellek tüketimine neden olan, tarayıcıya bağlanan daha az olayın olmasının avantajına sahiptir; Eğer bir oyun yapıyorsanız temsilci seçmeyin.
vipero07

1
Referans verdiğiniz "test sayfası" çalışmıyor.
Jaime Montoya

Yanıtlar:


374

Durum 1 (doğrudan):

$("div#target span.green").on("click", function() {...});

== Hey! Her açıklığı istiyorum. Div # target içindeki yeşil dinlemek için: tıkladığınızda X yapın.

Durum 2 (yetkilendirilmiş):

$("div#target").on("click", "span.green", function() {...});

== Hey, div # target! "Span.green" alt öğelerinizden herhangi biri tıklandığında, onlarla X yapın.

Diğer bir deyişle...

Durum 1'de, bu açıklıkların her birine ayrı ayrı talimatlar verilmiştir. Yeni açıklıklar oluşturulursa, talimatı duymazlar ve tıklamalara yanıt vermezler. Her açıklık doğrudan sorumludur kendi olaylarından .

2. durumda, sadece konteynere talimat verilmiştir; alt öğeleri adına yapılan tıklamaları fark etmekten sorumludur . Olay yakalama çalışmaları devredildi . Bu aynı zamanda talimatın gelecekte oluşturulacak alt öğeler için gerçekleştirileceği anlamına gelir.


46
Bu harika bir açıklama ve uzun zamandır anlamayı reddettiğim bir konuya netlik getirdi. Teşekkürler!
dgo

3
Öyleyse neden on()iki argümana izin verdiğinizde, bunun kullanımı kullanmakla aynı olur click()?
nipponese

5
.on (), birden fazla farklı etkinlik de dahil olmak üzere her türlü etkinliği işleyebilen genel amaçlı bir API'dır (bu ilk dizeye birden çok etkinlik adı koyabilirsiniz.) .click (), bu ilk form için yalnızca bir kısayoldur.
N3dst4

1
@newbie, @ N3dst4: e.targettıklama etkinliğinin başlangıç ​​hedefi olacaktır (çocuk varsa bir alt düğüm olabilir span.green). İşleyicinin içinden thisreferansı kullanmalısınız . Bu kemanı gör .
LeGEC

1
Delegasyon konusuna eklemek için bir başka not - hem çok yararlı hem de çok verimli. Yetki verilen her öğeye bir etkinlik eklemek veya yetki vermek için daha az tarayıcı kaynağı kullanırsınız. İnsanların delegasyonu kullanmak için daha fazla nedene ihtiyaç duymaları durumunda bundan söz edeceğimi düşündüm.
phatskat

6

İlk yol, $("div#target span.green").on() bir tıklama işleyiciyi doğrudan kod yürütülürken seçiciyle eşleşen açıklıklara bağlar. Bu, daha sonra başka açıklıklar eklenirse (veya sınıfları eşleşecek şekilde değiştirilirse) kaçırıldıkları ve tıklama işleyicileri olmayacakları anlamına gelir. Ayrıca, daha sonra "green" sınıfını tıklama işleyicisinin çalışmaya devam edeceği anlamına gelir - jQuery, işleyicinin nasıl atandığını ve seçicinin hala eşleşip eşleşmediğini kontrol etmez.

İkinci yol, $("div#target").on()bir tıklama işleyicisini eşleşen div (s) öğelerine bağlar (yine, o anda eşleşenlere karşıdır), ancak div'ın herhangi bir yerinde bir tıklama gerçekleştiğinde işleyici işlevi yalnızca tıklama yalnızca .on()div'de değil, "span.green" ile ikinci parametrede seçici eşleşen bir alt öğede oluştu. Bu şekilde yapıldığında, bu açıklıkların ne zaman oluşturulduğu önemli değildir, üzerlerine tıklamak işleyiciyi çalıştırmaya devam edecektir.

Dolayısıyla, içeriğini dinamik olarak eklemeyen veya değiştirmeyen bir sayfa için iki yöntem arasında bir fark görmezsiniz. Ek alt öğeleri dinamik olarak ekliyorsanız, ikinci sözdizimi, üst öğeye zaten bir kez yaptığınız için onlara tıklama işleyicileri atama konusunda endişelenmenize gerek olmadığı anlamına gelir.


5

N3dst4'ün açıklaması mükemmel. Buna dayanarak, tüm alt öğelerin vücut içinde olduğunu varsayabiliriz, bu nedenle sadece bunu kullanmamız gerekir:

$('body').on('click', '.element', function(){
    alert('It works!')
});

Doğrudan veya temsilci etkinliğiyle çalışır.


2
jquery, daha yavaş olduğu için vücudu kullanmaya karşı tavsiyede bulunur, çünkü senaryo, çoğu durumda çok olması gereken vücuttaki tüm çocukları aramalıdır. Elemanın ara ana kabını kullanmak daha iyidir (daha hızlı).
mikesoft

1
Jquery, gösterdiğin gibi yapan canlı yöntemi kaldırdı. Bu performans zayıftır ve kullanılmamalıdır.
Maciej Sikora

Modern tarayıcılarda, $('body').on()gelen heyet .elementyerli ile aynı şekilde hareket etmelidir document.body.addEventHandler()bir ile if (Event.target.className.matches(/\belement\b/))geri aramasında. $.proxyHavai nedeniyle jquery'de biraz daha yavaş olabilir, ancak bana bu konuda alıntı yapmayın.
cowbert

2

OP'ye teğet, ancak bu özellikle karışıklığı çözmeme yardımcı olan kavram , bağlı öğelerin seçilen öğelerin ebeveynleri olması gerektiğidir .

  • Bağlı, geriye kalanları ifade eder .on.
  • Seçilen, 2. argümanı ifade eder .on().

Temsilci seçme, bağlı öğelerin bir alt kümesini seçerek .find () gibi çalışmaz. Seçici yalnızca katı alt elemanlar için geçerlidir.

$("span.green").on("click", ...

çok farklı

$("span").on("click", ".green", ...

Özellikle, @ N3dst4'ün avantajlarını elde etmek için "gelecekte yaratılan elemanlar" ile ilgili ipuçları, bağlı elemanın kalıcı bir ebeveyn olması gerekir . Sonra seçilen çocuklar gelip gidebilirler.

DÜZENLE

Temsilci seçmenin neden .onçalışmadığı kontrol listesi

Çalışmamasının $('.bound').on('event', '.selected', some_function)zor nedenleri :

  1. Bağlı eleman kalıcı değildir . Aradıktan sonra oluşturuldu.on()
  2. Seçilen öğe, bağlı öğenin uygun bir alt öğesi değil. Aynı unsur.
  3. Seçilen öğe , bir olayın çağrılarak ilişkili öğeye köpürmesini engelledi .stopPropagation().

(Yanlış yazılmış bir seçici gibi daha az zorlayıcı nedenleri atlamak.)


1

Doğrudan olayların karşılaştırılması ile bir yazı yazdım ve yetki verdim. Saf js karşılaştırmak ama jquery için sadece onu çevreleyen aynı anlama sahiptir.

Sonuç, yetki verilen olay işlemenin, kullanıcı sayfa ile etkileşime girdiğinde (tekrar ciltlemeye gerek yokken) bağlı öğelerin oluşturulabileceği dinamik DOM yapısı için olduğu ve yapının değişmeyeceğini bildiğimizde doğrudan olay işlemenin statik DOM öğeleri için olduğu yönündedir.

Daha fazla bilgi ve tam karşılaştırma için - http://maciejsikora.com/standard-events-vs-event-delegation/

Her zaman çok güncel olduğunu gördüğüm her zaman temsilci işleyicileri kullanmak doğru değil, birçok programcı bunu kullanmalıdır çünkü "kullanılmalıdır", ancak gerçek şu ki, doğrudan olay işleyicileri bazı durumlar için daha iyi ve hangi yöntem kullanımının desteklenmesi gerektiği farklılıklar bilgisiyle.


çok sayıda olay işleyicisi (örneğin, bir tablonun her satırı) ekleniyorsa, birçok doğrudan işleyici eklemek yerine konteynere tek temsilci işleyici kullanmak genellikle daha iyi performans gösterir. Bunu, olay işleyici sayısının kendi başına bir profil oluşturma metriği olduğu gerçeğinden görebilirsiniz.
cowbert
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.