JQuery `click`,` bind`, `live`, 'delege`,' trigger` ve` on` işlevleri arasındaki fark (bir örnekle)?


139

Her bir işlevin belgelerini okudum jQuery official website, ancak aşağıdaki işlevler 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 işlevler tam olarak nasıl çalışır ve hangi durumda hangisi tercih edilmelidir?

Not: Aynı işlevselliğe veya mekanizmaya sahip başka işlevler varsa, lütfen ayrıntılı olarak belirtin.

Güncelleme

Ben de bir $.triggerfonksiyon gördüm . Yukarıdaki işlevlere benzer mi?

Daha Fazla Güncelleme

Şimdi v1.7'de.on eklendi ve bence bu bir şekilde yukarıdaki tüm fonksiyon gereksinimlerini birlikte karşıladı.


3
@I PHP gibi, bazen bir kılavuz tarafından cevaplanamayan veya bir ev ödevi sorusu gibi görünmeyen bir soru olduğunu düşünmüyorlarsa insanlar oy kullanırlar. Endişelenmeyin, başkaları yararlı bulduklarında oy kullanacaktır.
typeoneerror

@ Typeoneerror - Destek için teşekkürler, ben zaten kılavuzu okumak ve ne zaman ben net fark anlamadıysanız ben burada sonrası.
diEcho

3
@I PHP gibi - Sorunu biraz temizleme için düzenledi ... bu genellikle sorulur, ancak nadiren bu şekilde, google uyumlu bir kaynak olabilir. Bunun gibi bir şeyin wiki-ish girişinin çok yardımcı olacağını kabul ediyorum , mükemmel bir soru için özellikle .live()ve .delegate()neredeyse her gün +1 ile ilgili karışıklık görüyorum .
Nick Craver

@Nick Craver Düzenlediğiniz için teşekkürler, aslında ingilizce im lol (lol). nasıl soru göndereceğimiz herhangi bir maunal / referans var mı SO? ot o deneyim tarafından geldi
diEcho

@I PHP gibi - Her ikisi de biraz, burada SO için harika bir all-around SSS var: meta.stackexchange.com/questions/7931 İfade / yorumlar için, neyin uygun olduğunu ve en iyi yol olduğunu öğrenmeye başlayabilirsiniz düşüncelerinizi iletmek, kod> bazen herhangi bir açıklama, doğru anahtar kelimeyi kullanarak, uygun şekilde etiketleme, sadece sanırım burada daha uzun geliyor sanırım, zamanla düzelen posterler çok görüyorum. Düzenlemenize gelince .trigger(), olay işleyiciyi çağırıyor ... Aşağıdaki cevabım için bir açıklama ekleyeceğim.
Nick Craver

Yanıtlar:


162

Bunu okumadan önce, bu etkinlik listesini başka bir sayfada kaldırın, API'nın kendisi son derece yararlıdır ve aşağıda tartıştığım şeylerin tümü doğrudan bu sayfadan bağlantılıdır .

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

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

Bu eleman değiştirilir veya atılırsa, bu işleyici artık orada olmayacaktır. Ayrıca , işleyici eklemek için bu kod çalıştırıldığında orada olmayan elemanlar (örneğin, seçici onu buldu) işleyiciyi alamaz.

.live()ve .delegate()benzer şekilde ilişkilidir, .delegate()aslında .live()dahili olarak kullanır , her ikisi de olayları kabarcık haline getirir. Bu yeni ve eski unsurlar için çalışır , olayları aynı şekilde kabarcıklar. Bunları öğeleriniz değiştiğinde, örneğin yeni satırlar, liste öğeleri vb. Eklediğinizde kullanırsınız. Sayfada kalacak ve hiçbir noktada değiştirilmeyecek bir üst / ortak ataya sahip değilseniz, aşağıdakini kullanın .live():

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

Bununla birlikte, değiştirilmeyen bir yerde bir üst öğeniz varsa (böylece olay işleyicileri güle güle gitmez) .delegate(), bununla başa çıkmalısınız :

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

Bu neredeyse aynı şekilde çalışır .live(), ancak olay yakalanmadan ve işleyicilerin idam edilmesinden önce daha az kez kabarcıklar. Her ikisinin de bir diğer yaygın kullanımı, sınıfınızın bir öğe üzerinde değiştiğini, artık kullandığınız seçiciyle eşleşmediğini ... bu yöntemlerle seçicinin olay sırasında değerlendirildiği , eğer eşleşmesi durumunda , işleyicinin çalıştığı .. böylece öğe artık seçici konularla eşleşmiyor, artık yürütülmeyecek. Bununla .click()birlikte, olay işleyicisi doğrudan DOM öğesine bağlanır, ilgisiz olduğunu bulmak için kullanılan herhangi bir seçiciyle eşleşmemesi gerçeği ... olay bağlanır ve bu öğe gidene veya işleyici kalıncaya kadar kalır , üzerinden kaldırıldı .unbind().

Yine bir başka yaygın kullanımı .live()ve .delegate()bir performans . Çok sayıda öğe ile uğraşıyorsanız , her bir öğeye doğrudan bir tıklama işleyicisi eklemek pahalı ve zaman alıcıdır. Bu durumlarda, tek bir işleyici kurmak ve köpürmenin işi yapmasına izin vermek, büyük bir fark yarattığı bu soruya bir göz atmak daha ekonomiktir , uygulamanın iyi bir örneğidir.


Tetikleme - güncellenmiş soru için

Kullanılabilir 2 ana olay işleyici tetikleme işlevi vardır, bunlar API'da aynı "Olay İşleyici Eki" kategorisine girer , bunlar .trigger()ve .triggerHandler(). .trigger('eventName')ortak etkinlikler için yerleşik bazı kısayollara sahiptir, ö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ısayolları içeren bir girişi burada görüntüleyebilirsiniz .

Fark gelince .trigger(), olay işleyiciyi tetikler (ancak çoğu zaman varsayılan eylemi değil, örneğin imleci tıklatılan doğru noktaya yerleştirme <textarea>). Olay işleyicilerinin bağlı oldukları sırada (yerel etkinliğin yaptığı gibi) gerçekleşmesine neden olur, yerel olay eylemlerini tetikler ve DOM'u havaya uçurur.

.triggerHandler()genellikle farklı bir amaç içindir, burada yalnızca bağlı işleyiciyi / işleyicileri kovmaya çalışıyorsunuz, yerel etkinliğin tetiklenmesine neden olmaz, örneğin bir form gönderme. DOM'u patlatmaz ve zincirlenebilir değildir (o olay için son bağlı olay işleyiciyi döndürürse döndürür). Örneğin, bir focusolayı tetiklemek istiyor ancak nesneyi gerçekten odaklamak istemiyorsanız, yalnızca bağlı olduğunuz kodun .focus(fn)çalışmasını istiyorsunuz, .trigger()bunu yaparsınız, bunu yaparken öğeye odaklanıp kabarırsınız.

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

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

Bu, herhangi bir gönderme işleyicisini, örneğin jQuery doğrulama eklentisini çalıştırır ve ardından göndermeyi dener <form>. Ancak, yalnızca bir submitolay işleyici aracılığıyla bağlandığından , ancak <form>daha sonra göndermediğinden doğrulamak istiyorsanız, şöyle kullanabilirsiniz .triggerHandler('submit'):

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

Eklenti, doğrulama denetiminin geçememesi durumunda işleyicinin formu bombalayarak göndermesini önler, ancak bu yöntemle ne yaptığını umursamıyoruz. O iptal veya olmasın biz değiliz İster çalışırken formu göndermek için, sadece yeniden doğrula bunu tetikleyebilir ve başka bir şey yapmak istedim. ( Feragatname: Bu, .validate()eklentide bir yöntem olduğu için gereksiz bir örnektir , ancak niyeti iyi bir şekilde göstermektedir)


Çok titiz. Küçük bir düzeltme: triggeryerel bir olayı başlatmaz. Yerli olarak fireEvent(IE) veya dispatchEvent(w3c) ile simüle edilmiş bir olayı kastediyorum .
Crescent Fresh

@Crescent - Daha az belirsiz olması için güncellendi, ben form gönderme, bağlantı aşağıdaki vb gibi yerel olay eylemleri ateş anlamına geliyordu ... umarım güncelleme daha açıktır :)
Nick Craver

@ Okuduğum kadarıyla, ele geçirmenizin live()bana burada verdiğinizden farklı olduğu görülüyor : stackoverflow.com/questions/3981762/… 'Ağırlık' kullanırken hala bir endişe live()mi var?
Yahel

@yahelc - Evet, elbette ... bu cevap olay işleyicilerinin seçeneklerini ve özel amaçlarını kesinlikle karşılaştırıyor. Başlangıç ​​maliyetine karşı ilk bağlama sayısı ve ilk seçiciye dinamik bir şey eklerseniz, yine de geçerli olan endişelerdir. Sayfa yapısı o kadar büyük değilse, o kadar çok etkinliğe sahip değilsiniz demektir, o zaman iyi olursunuz ... ağırlık konusundaki endişe, yapınızın boyutu / derinliği ve etkinlik sayısı ile orantılıdır ( her biri için seçiciler çalıştırdığından, .live()aramanızın dinlediği türü ( ör. click) oluşturuluyor.
Nick Craver

1
jQuery 1.7'de live (), $ (document) .on () lehine kullanımdan kaldırılmıştır.
Synchro

28

İlk ikisi eşdeğerdir.

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

İkincisi, boşlukla ayrılmış birkaç olay adı belirterek aynı anda birden fazla olaya bağlamak için kullanılabilir:

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

.liveYöntem daha ilginçtir. Aşağıdaki örneği düşünün:

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

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

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

Komut dosyasının ikinci satırı yürütüldükten sonra, ikinci bağlantının "myLink" CSS sınıfı da olacaktır. Ancak olay işleyicisine sahip olmayacaktır, çünkü olay eklendiğinde sınıfa sahip değildi.

Şimdi bunun tam tersi olmasını istediğinizi düşünün: sayfada "myLink" sınıfında bir bağlantı her görüntülendiğinde, otomatik olarak aynı olay işleyiciye sahip olmasını istersiniz. Dinamik olarak satır veya hücre eklediğiniz, ancak hepsinin aynı şekilde davranmasını istediğiniz bir tür liste veya tablo varsa, bu çok yaygındır. Olay işleyicilerini her seferinde yeniden atamanın tüm acısına gitmek yerine, .liveyöntemi 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ı "myLink" sınıfını alır almaz olay işleyicisini de alacaktır. Sihirli! :-)

Tabii ki, tam anlamıyla değil. .liveGerçekten ne yaparsa, işleyiciyi belirtilen öğeye değil, HTML ağacının ("gövde" öğesi) köküne ekleyin. DHTML'deki etkinlikler bu "fokurdama" özelliğine sahiptir. Bunu düşün:

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

"Metin" i tıklarsanız, önce <b> öğesi bir "tıklama" etkinliği alır. Bundan sonra, <a> öğesi bir "click" etkinliği alacaktır. Bundan sonra <div> öğesi bir "click" etkinliği alacaktır. Ve böylece - <body> öğesine kadar. Ve burada jQuery olayı yakalayacak ve olaya neden olan öğeye uygulanan "canlı" işleyiciler olup olmadığını görecek. Temiz!

Ve son olarak, .delegateyöntem. Öğenizin verilen seçiciye uyan tüm çocuklarını alır ve onlara "canlı" bir işleyici bağlar. Bir göz at:

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

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

Sorular?


Doğru olabilmesi için, .live()hiç bağlar documentdeğil <body>:) Burada bir demo izleyebilirsiniz, sadece incelemek için konsolu yukarı çekin: jsfiddle.net/aJy2B
Nick Craver

3
Bunu bu şekilde açıklamak daha uygun oldu. :-)
Fyodor Soikin

4
"Gövde" kısmında yeterince adil, ancak "<body> elementine" kadar yol yanlış, olaylar orada geçmeye devam ediyor ve .live()işleyicilerin yaşadığı yer değil , bunun üstünde, üzerinde document:) demo burada: jsfiddle.net/S2VBX
Nick Craver

8

JQuery 1.7 itibariyle .live () yöntemi kullanımdan kaldırıldı. Bir jQuery sürümü <1,7 kullanıyorsanız, .live () üzerinden .delegate () kullanılması resmi olarak önerilir.

.live () artık .on () ile değiştirildi.

Daha fazla bilgi için doğrudan jQuery sitesine gitmek en iyisidir, ancak .on () yönteminin geçerli sürümleri şunlardır:

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

http://api.jquery.com/on/


2

$().click(fn)ve $().bind('click', fn)ilk bakışta aynıdır, ancak $.bindsürüm iki nedenden dolayı daha güçlüdür:

  1. $().bind()bir işleyiciyi birden çok etkinliğe atamanıza olanak tanır, örneğin $().bind('click keyup', fn).
  2. $().bind()ad boşluklu olayları destekler - yalnızca bir öğenin bağlı olduğu belirli olay işleyicilerini kaldırmak (açmak) için güçlü bir özellik - Ad Aralığı Olayları'nda daha fazla bilgi edinin .

Canlı ve delege: Bu, diğer yanıtlarda zaten yanıtlandı.


1

API okumak burada yardımcı olabilir. Ancak, kafamın üst kısmını biliyorum, böylece tembel olmaya devam edebilirsiniz (yay!).

$('#something').click(fn);
$('#something').bind('click',fn);

Burada hiçbir fark yok (bildiğim kadarıyla). .clickbasitçe bir kolaylık / yardımcı yöntemdir.bind('click'

// even after this is called, all <a>s in
// <div class="dynamic_els"> will continue
// to be assigned these event handlers

$('div.dynamic_els a').live(‘click’,fn);

Bu, çok farklıdır, çünkü .livegeçtiğiniz seçiciye etkinlik ekler (burada bulunmuyorsunuz) ve düğümler eklendiğinde / kaldırıldıkça DOM'a bakmaya devam ediyor

$('#some_element').delegate('td','click',fn);

Bu yalnızca olay işleyicileri atama şekliniz nedeniyle farklıdır. .delegate, DOM olayının köpürmesine odaklanmıştır. Temel ilke, her olayın kök öğeye ulaşana kadar ( documentya windowda <html>ya da <body>tam olarak hatırlayamıyorum) DOM ağacında yukarı doğru kabarmasıdır .

Her iki durumda da, bir onclickişleyiciyi <td>içindeki tüm özelliklere bağlarsınız $('#some_element')(söyleyebilmenize rağmen bir seçici belirtmelisiniz $(document)). Çocuklarından biri tıklatıldığında, olay <td>. Daha sonra olayın kaynak öğesini çıkarabilirsiniz (jQuery sizin için otomatik olarak yapar).

Bu, tonlarca öğe olduğunda ve bu olayların geçeceği yalnızca birkaç (veya bir merkezi) noktaya sahip olduğunuzda yararlıdır. Bu, bu olay işleyicilerini daha az nesnede birleştirmek için tarayıcı çabasını ve belleğini korur.


1
.live() Ayrıca gerçeği de, olay köpüren kulanan .delegate()için bir sarıcı .live(), sadece bir bağlam eklemeye ve bir öğeye bağlanmasını oluyor diğer daha documentkabarcıklar yakalamak için. Fokurdayan işleyicilerin nasıl çalıştığına dair anlayışınız biraz kapalı (bence jQuery 1.4'ün en sık yanlış anlaşılan yönü). İşleyicisi olan sadece bu yüzden denilen ne eleman, aşağıda belirtilen yerlere bağlı elemana .delegate()üzerinde veya documentdurumunda .live()bir olay oraya kabarcıklar olduğunda, bu takdirde yürütür yüzden seçici ile eşleşir olmadığını görmek için hedef denetler ve.
Nick Craver
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.