javascript - jQuery `click`, `bind`, `live`, `delegate`, `trigger` ve `on` fonksiyonları arasındaki fark (örnek ile)?


Her bir fonksiyonun belgelerini jQuery resmi web sitesinde okudum, ancak aşağıdaki fonksiyonlar arasında böyle bir karşılaştırma listesi yok:

$().click(fn)
$().bind('click',fn)
$().live('click',fn)
$().delegate(selector, 'click', fn)
$().trigger('click') // UPDATED
$().on('click', selector ,fn); // more UPDATED

Lütfen herhangi bir referans bağlantısından kaçının.

Yukarıdaki tüm fonksiyonlar tam olarak nasıl çalışır ve hangi durumda hangisi tercih edilmelidir?

Not: Eğer aynı işlevselliğe veya mekaniğe sahip başka bir fonksiyon(lar) varsa, lütfen detaylandırın.

Güncelle

Ayrıca bir $.trigger fonksiyonu da gördüm. Bu, yukarıdaki fonksiyonlara benzer şekilde mi çalışıyor?

Daha Fazla Güncelleme

Şimdi .on v1.7'de eklenmiş ve bence bu, yukarıdaki tüm fonksiyonların gereksinimlerini bir şekilde birlikte kapsıyor.

Cevap #1

Bunu okumadan önce, bu olay listesini başka bir sayfada açın, API kendisi son derece faydalıdır ve aşağıda tartıştığım her şey doğrudan bu sayfadan bağlantılıdır.

İlk olarak, .click(function) kelimenin tam anlamıyla .bind('click', function) için bir kısayoldur, bunlar eşdeğerdir. Bir işleyiciyi doğrudan bir elemana bağlarken bunu kullanın, şöyle:

$(document).click(function() {
  alert("You clicked somewhere in the page, it bubbled to document");
});

Eğer bu öğe değiştirilir veya atılırsa, bu işleyici artık orada olmayacaktır. Ayrıca, bu kod çalıştırıldığında işleyiciyi eklemek için mevcut olmayan öğeler (örneğin, seçici o zaman buldu) işleyiciyi almayacaktır.

.live() ve .delegate() benzer şekilde ilişkilidir, .delegate() aslında dahili olarak .live() kullanır, ikisi de olayların yayılmasını dinler. Bu, yeni ve eski öğeler için çalışır, olayları aynı şekilde yayarlar. Öğeleriniz değişebileceğinde bunları kullanırsınız, örneğin yeni satırlar, liste öğeleri eklemek gibi. Sayfada kalacak ve hiçbir şekilde değiştirilmeden kalacak bir ebeveyn/ortak ata yoksa, .live() kullanın, şöyle:

$(".clickAlert").live('click', function() {
  alert("A click happened");
});

Ancak eğer bir yerlerde değiştirilmeyen bir ebeveyn öğeniz varsa (yani olay işleyicileri gitmiyorsa), bunu .delegate() ile şöyle ele almalısınız:

$("#commonParent").delegate('.clickAlert', 'click', function() {
  alert("A click happened, it was captured at #commonParent and this alert ran");
});

Bu, neredeyse .live() ile aynı şekilde çalışır, ancak olay yakalanmadan ve işleyiciler çalıştırılmadan önce olay daha az sayıda kabarır. Her iki yöntemin bir diğer yaygın kullanımı ise, diyelim ki bir öğenin sınıfı değişiyor ve artık başlangıçta kullandığınız seçiciyle eşleşmiyor... bu yöntemlerde seçici olay zamanında değerlendirilir, eşleşiyorsa işleyici çalışır... bu nedenle seçici ile artık eşleşmeyen öğe önemli değildir, artık çalıştırılmaz. Ancak .click() ile olay işleyici doğrudan DOM öğesine bağlanır, kullanılan seçiciyle eşleşmemesi önemsizdir... olay bağlanmıştır ve o öğe gitmediği veya işleyici .unbind() ile kaldırılmadığı sürece kalır.

.live() ve .delegate() için bir diğer yaygın kullanım performanstır. Eğer çok sayıda öğeyle uğraşıyorsanız, her öğeye doğrudan bir tıklama işleyicisi eklemek maliyetli ve zaman alıcıdır. Bu durumlarda, tek bir işleyici kurmak ve kabarcıklanmanın işini yapmasına izin vermek daha ekonomiktir, büyük fark yarattığı bir soruya bakabilirsiniz, uygulamanın iyi bir örneğidir.

Tetikleme - güncellenmiş soru için

İki ana olay işleyici tetikleme fonksiyonu mevcuttur, bunlar API'de aynı "Olay İşleyici Eki" kategorisine girer, bunlar .trigger() ve .triggerHandler() fonksiyonlarıdır. .trigger('eventName') bazı yaygın olaylar için yerleşik bazı kısayollar içerir, örneğin:

$().click(fn); //binds an event handler to the click event
$().click();   //fires all click event handlers for this element, in order bound

Bu kısayollardan oluşan bir listeyi burada görüntüleyebilirsiniz.

Fark açısından, .trigger() olay işleyiciyi tetikler (ancak çoğu zaman varsayılan eylemi tetiklemez, örneğin tıklanan bir <textarea> içinde imleci doğru konuma yerleştirmek). Olay işleyicilerin bağlı oldukları sırayla gerçekleşmesini sağlar (yerel olayda olduğu gibi), yerel olay eylemlerini tetikler ve DOM üzerinde yukarı doğru yayılır.

.triggerHandler() genellikle farklı bir amaç için kullanılır, burada sadece bağlı işleyici(leri) tetiklemeye çalışıyorsunuz, bu, yerel etkinliğin (örneğin bir formu gönderme) tetiklenmesine neden olmaz. DOM üzerinde yukarı doğru yayılmaz ve zincirleme yapılamaz (o olay için en son bağlı etkinlik işleyicisinin döndürdüğünü döndürür). Örneğin, bir focus olayını tetiklemek istiyorsunuz ama nesneyi gerçekten odaklamak istemiyorsunuz, sadece .focus(fn) ile bağlı kodun çalışmasını istiyorsanız, bu bunu yapar; oysa .trigger() bunu yapmasının yanı sıra öğeyi gerçekten odaklar ve yukarı doğru yayılır.

İşte gerçek bir dünya örneği:

$("form").submit(); //actually calling `.trigger('submit');`

Bu, örneğin jQuery doğrulama eklentisi gibi, tüm gönderim işleyicilerini çalıştırır ve ardından <form> göndermeye çalışır. Ancak eğer sadece doğrulamak istiyorsanız, çünkü bir submit olay işleyicisi ile bağlanmış ama daha sonra <form> göndermeyecekse, .triggerHandler('submit') kullanabilirsiniz, şöyle:

$("form").triggerHandler('submit');

Eklenti, doğrulama kontrolü geçmezse işlemi durdurarak formun gönderilmesini engelliyor, ama bu yöntemde ne yaptığı umurumuzda değil. Formu göndermeyi denemiyoruz, sadece tekrar doğrulaması için tetiklemek istedik ve başka bir şey yapmadık. (Uyarı: Bu gereksiz bir örnek çünkü eklentide bir .validate() yöntemi var, ama niyeti göstermek için iyi bir örnek.)

Cevap #2

İlk ikisi eşdeğerdir.

// The following two statements do the same thing:
$("blah").click( function() { alert( "Click!" ); } );
$("blah").bind( "click", function() { alert( "Click!" ); } ); 

Ancak ikinci olan, birkaç boşlukla ayrılmış olay adı belirterek aynı anda birden fazla olaya bağlanmak için kullanılabilir:

$("blah").bind( "click mouseover mouseout", function() { alert( "Click! Or maybe mouse moved." ); } ); 

.live yöntemi daha ilginç. Aşağıdaki örneği göz önünde bulundurun:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").click( function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

Betiğin ikinci satırı çalıştıktan sonra, ikinci bağlantı da "myLink" CSS sınıfına sahip olacaktır. Ancak, olay işleyicisine sahip olmayacaktır çünkü olay eklenirken sınıfa sahip değildi.

Şimdi bunu tersini istediğinizi düşünün: sayfada "myLink" sınıfına sahip bir bağlantı her göründüğünde, bunun otomatik olarak aynı olay işleyicisine sahip olmasını istiyorsunuz. Bu, bazı tür listeler veya tablolarla çalışırken çok yaygındır; satırları veya hücreleri dinamik olarak eklerken, hepsinin aynı şekilde davranmasını istersiniz. Olay işleyicilerini her seferinde yeniden atama zahmetine girmek yerine, .live metodunu kullanabilirsiniz:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").live( "click", function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

Bu örnekte, ikinci bağlantı da "myLink" sınıfını aldığı anda olay işleyiciyi alacaktır. Sihir gibi! :-)

Tabii ki, bu kadar kelimesi kelimesine değildir. .live aslında işlemi belirtilen elemana değil, HTML ağacının en köküne ("body" elementine) bağlar. DHTML'deki olayların bu "yukarı doğru kabarması" adlı ilginç bir özelliği vardır. Bunu düşünün:

<div> <a> <b>text</b> </a> </div>

Eğer "text" üzerine tıklarsanız, önce <b> elementi bir "click" olayı alacak. Bundan sonra, <a> elementi bir "click" olayı alacak. Ve bundan sonra <div> elementi bir "click" olayı alacak. Ve bu şekilde - <body> elementine kadar devam edecek. Ve jQuery olayın yakalandığı yer burası olacak ve ilk olarak olayı tetikleyen elemente uygulanabilecek herhangi bir "live" işleyici olup olmadığını görür. Harika!

Ve son olarak, .delegate yöntemi. Bu yöntem, öğenizin verilen seçiciye uyan tüm alt öğelerini alır ve onlara "canlı" bir işlemci ekler. Bir göz atın:

$("table").delegate( "td", "click", function() { alert( "Click!" ); } );

// Is equivalent to:
$("table").each( function() {
    $(this).find( "td" ).live( "click", function() { alert( "Click!" ); } );
} );

Sorular?

İlgili makaleler