Differenza tra jQuery `click`,` bind`, `live`,` delegate`, `trigger` e` on` (con un esempio)?


139

Ho letto la documentazione di ciascuna funzione jQuery official website, ma non ci sono elenchi di confronto tra le funzioni seguenti:

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

Si prega di evitare qualsiasi collegamento di riferimento.

Come funzionano esattamente tutte le funzioni precedenti e quale dovrebbe essere preferito in quale situazione?

Nota: se ci sono altre funzioni con la stessa funzionalità o meccanismo, si prega di elaborare.

Aggiornare

Ho visto anche una $.triggerfunzione. Funziona in modo simile alle funzioni sopra?

Altro aggiornamento

Ora .onè stato aggiunto in v1.7 e penso che questo in qualche modo copra tutti i requisiti di funzioni sopra insieme.


3
@Mi piace PHP, a volte le persone votano le cose in basso se non ritengono che sia una domanda a cui non è possibile rispondere con un manuale o che sembra essere una domanda a casa. non ti preoccupare, altre persone lo voteranno se lo trovano utile.
typeoneerror

@ Typeoneerror - Grazie per il supporto, ho già letto il manuale e quando non ho capito la chiara differenza allora inserisco qui.
diEcho,

3
@Mi piace PHP - Modificata la domanda per un po 'di pulizia ... questo viene spesso chiesto, ma raramente in questo modo, può facilmente essere una risorsa preziosa per Google. Concordo sul fatto che una voce wiki di qualcosa del genere sia molto utile, vedo confusione in questo, specialmente con .live()e .delegate()quasi ogni giorno, +1 per una domanda perfettamente valida.
Nick Craver

@Nick Craver Grazie per il montaggio, in realtà sto male in inglese (lol). c'è qualche riferimento / riferimento su come pubblicare una domanda SO. ot appena arrivato dall'esperienza
diEcho il

@Mi piace PHP - È un po 'di entrambi, ci sono ottime FAQ a tutto tondo per SO qui: meta.stackexchange.com/questions/7931 Per il fraseggio / commenti, inizi a imparare cosa si adatta ed è il modo migliore per trasmetti i tuoi pensieri, codifica> qualsiasi descrizione a volte, usando la parola chiave giusta, taggandola in modo appropriato, arriva più a lungo sei qui suppongo, vedo molti poster migliorare nel tempo. Per quanto riguarda la tua modifica, .trigger()invoca solo il gestore eventi ... Aggiungerò una descrizione alla mia risposta di seguito.
Nick Craver

Risposte:


162

Prima di leggere questo, estrai questo elenco di eventi in un'altra pagina, l'API stessa è straordinariamente utile e tutto ciò di cui sto discutendo di seguito è collegato direttamente da questa pagina .

Innanzitutto, .click(function)è letteralmente una scorciatoia per .bind('click', function), sono equivalenti. Usali quando associ un gestore direttamente a un elemento , in questo modo:

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

Se questo elemento viene sostituito o gettato via, questo gestore non sarà più lì. Inoltre, elementi che non erano presenti quando è stato eseguito questo codice per collegare il gestore (ad esempio, il selettore lo ha trovato in quel momento) non otterrà il gestore.

.live()e .delegate()sono collegati in modo simile, in .delegate()realtà utilizza .live()internamente, entrambi ascoltano gli eventi in bolla. Funziona con elementi nuovi e vecchi , fanno gli eventi nello stesso modo. Li usi quando i tuoi elementi possono cambiare, ad es. Aggiungendo nuove righe, elenchi di elementi, ecc. Se non hai un genitore / antenato comune che rimarrà nella pagina e non verrà sostituito in nessun punto, usa .live(), in questo modo:

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

Se comunque hai un elemento genitore da qualche parte che non viene sostituito (quindi i suoi gestori di eventi non ci salutano) dovresti gestirlo con .delegate(), in questo modo:

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

Funziona quasi allo stesso modo .live(), ma l'evento bolle meno volte prima di essere catturato e gli handler eseguiti. Un altro uso comune di entrambi è dire che la tua classe cambia su un elemento, non più corrispondente al selettore che hai usato originariamente ... con questi metodi il selettore viene valutato al momento dell'evento , se corrisponde, il gestore esegue .. . quindi l'elemento che non corrisponde più al selettore è importante, non verrà più eseguito. Con .click()tuttavia, il gestore di eventi è proprio legato sull'elemento DOM, il fatto che essa non corrisponde a ciò che di selezione è stato utilizzato per scoprire che è irrilevante ... l'evento è legato e che è rimanere fino a quel elemento è andato, o il gestore viene rimosso tramite .unbind().

Ancora un altro uso comune per .live()ed .delegate()è la prestazione . Se hai a che fare con molti elementi, collegare un gestore di clic direttamente a ciascun elemento è costoso e richiede tempo. In questi casi è più economico impostare un singolo gestore e lasciare che il gorgogliamento faccia il lavoro, dai un'occhiata a questa domanda in cui ha fatto un'enorme differenza , è un buon esempio dell'applicazione.


Trigger : per la domanda aggiornata

Sono disponibili 2 principali funzioni di attivazione del gestore eventi, che rientrano nella stessa categoria "Collegamento gestore eventi" nell'API , queste sono .trigger()e .triggerHandler(). .trigger('eventName')ha alcune scorciatoie integrate per gli eventi comuni, ad esempio:

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

Puoi visualizzare un elenco che include queste scorciatoie qui .

Per quanto riguarda la differenza, .trigger()attiva il gestore eventi (ma non l'azione predefinita per la maggior parte del tempo, ad esempio posizionando il cursore nel punto giusto in un clic <textarea>). Fa sì che i gestori di eventi si verifichino nell'ordine in cui erano associati (come farebbe l'evento nativo), attiva le azioni dell'evento nativo e crea bolle nel DOM.

.triggerHandler()di solito è per uno scopo diverso, qui stai solo cercando di licenziare i gestori associati, non provoca l'evento nativo, ad esempio l'invio di un modulo. Non crea bolle nel DOM e non è concatenabile (restituisce qualunque sia il gestore dell'evento associato all'ultimo limite per quell'evento). Ad esempio, se si desidera attivare un focusevento ma non focalizzare effettivamente l'oggetto, si desidera semplicemente .focus(fn)eseguire il codice con cui si esegue il binding , ciò farebbe ciò, mentre .trigger()lo si farebbe così come focalizzare l'elemento e fare bolle.

Ecco un esempio del mondo reale:

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

Ciò eseguirà qualsiasi gestore di invio, ad esempio il plugin di convalida jQuery , quindi tenterà di inviare il file <form>. Tuttavia, se si desidera solo convalidare, poiché è collegato tramite un submitgestore eventi, ma non inoltrare <form>successivamente, è possibile utilizzare .triggerHandler('submit'), in questo modo:

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

Il plug-in impedisce al gestore di inviare il modulo bombardando se il controllo di convalida non passa, ma con questo metodo non ci interessa cosa fa. Che si sia interrotto o meno, non stiamo cercando di inviare il modulo, volevamo solo attivarlo per riconvalidare e fare nient'altro. ( Dichiarazione di non responsabilità: questo è un esempio superfluo poiché esiste un .validate()metodo nel plugin, ma è una buona illustrazione dell'intento)


Molto approfondito. Una piccola correzione: triggernon attiva un evento nativo. Per nativo intendo un evento simulato con fireEvent(IE) o dispatchEvent(w3c).
Crescent Fresh,

@Crescent - Aggiornato per essere meno ambiguo, intendevo dire che attiva le azioni degli eventi nativi , come l'invio di moduli, il collegamento che segue ecc ... speriamo che l'aggiornamento sia più chiaro :)
Nick Craver

@Nick da quello che sto leggendo, sembra che la tua opinione live()sia diversa da quella che mi hai dato qui: stackoverflow.com/questions/3981762/… Il 'peso' è ancora un problema durante l'utilizzo live()?
Yahel,

@yahelc - Sì, certo ... questa risposta sta confrontando rigorosamente le opzioni dei gestori di eventi e il loro scopo specifico. Il costo ponderale rispetto al numero di attacchi iniziali vs. se stai aggiungendo qualcosa in modo dinamico rispetto al selettore iniziale sono tutti problemi ancora validi. Se la tua struttura di pagina non è così grande da non avere così tanti eventi, allora stai bene ... la preoccupazione per il peso è direttamente proporzionale alla dimensione / profondità della struttura e al numero di eventi (di il tipo di .live()ascolto della chiamata, ad es. click) che vengono generati, poiché esegue selettori per ognuno.
Nick Craver

1
in jQuery 1.7, live () è deprecato a favore di $ (document) .on ().
Synchro,

28

I primi due sono equivalenti.

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

Il secondo, tuttavia, può essere utilizzato per associare più di un evento contemporaneamente, specificando diversi nomi di eventi separati da spazi:

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

Il .livemetodo è più interessante Considera il seguente esempio:

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

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

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

Dopo l'esecuzione della seconda riga dello script, il secondo collegamento avrà anche una classe CSS di "myLink". Ma non avrà il gestore dell'evento, perché non aveva la classe quando l'evento era associato.

Ora considera che volevi che fosse il contrario: ogni volta che un link con la classe "myLink" appare da qualche parte nella pagina, vuoi che abbia lo stesso gestore di eventi automaticamente. Questo è molto comune quando si dispone di una sorta di elenchi o tabelle, in cui si aggiungono righe o celle in modo dinamico, ma si desidera che tutti si comportino allo stesso modo. Invece di andare di nuovo tutto il dolore di assegnare nuovamente i gestori di eventi, puoi usare il .livemetodo:

<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>

In questo esempio, il secondo collegamento otterrà anche il gestore eventi non appena ottiene la classe "myLink". Magia! :-)

Certo, non è così letterale. Ciò che .liverealmente fa è collegare il gestore non all'elemento specificato stesso, ma alla radice stessa dell'albero HTML (l'elemento "body"). Gli eventi in DHTML hanno questa divertente caratteristica di "gorgogliare". Considera questo:

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

Se fai clic su "testo", prima l'elemento <b> riceverà un evento "clic". Successivamente, l'elemento <a> riceverà un evento "clic". E successivamente l'elemento <div> riceverà un evento "click". E così via, fino all'elemento <body>. Ed è qui che jQuery catturerà l'evento e vedrà se ci sono gestori "live" che si applicano all'elemento che ha causato l'evento in primo luogo. ! Neat

E infine, il .delegatemetodo. Prende semplicemente tutti i figli del tuo elemento che si conformano al selettore dato e allegano un gestore "live" a loro. Guarda:

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

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

Domande?


Per essere precisi, si .live()lega a documentnon <body>:) Puoi vedere una demo qui, basta aprire la console per ispezionare: jsfiddle.net/aJy2B
Nick Craver

3
Era più conveniente spiegarlo in questo modo. :-)
Fyodor Soikin il

4
Abbastanza giusto sulla parte "body", ma "fino all'elemento <body>" è sbagliato, gli eventi continuano a passare lì, e non è dove .live()vivono i gestori, è sopra quello, su document:) Puoi vedere un demo di questo qui: jsfiddle.net/S2VBX
Nick Craver

8

A partire da jQuery 1.7, il metodo .live () era obsoleto. Se si utilizza una versione jQuery <1.7 di quella consigliata, si consiglia di utilizzare .delegate () su .live ().

.live () è stato ora sostituito con .on ().

È meglio andare direttamente al sito jQuery per ulteriori informazioni, ma ecco le versioni correnti del metodo .on ():

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

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


2

$().click(fn)e $().bind('click', fn)sono identici a prima vista, ma la $.bindversione è più potente per due motivi:

  1. $().bind()consente di assegnare un gestore a più eventi, ad esempio $().bind('click keyup', fn).
  2. $().bind()supporta eventi con spazio dei nomi - una potente funzione se si desidera rimuovere (separare) solo alcuni gestori di eventi a cui è legato un elemento - leggi di più in Eventi con spazio dei nomi .

Delegato vs diretto: questo ha già ricevuto risposta nelle altre risposte.


1

È qui che potrebbe essere utile leggere l'API. Tuttavia, lo so dalla cima della mia testa, quindi puoi continuare ad essere pigro (yay!).

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

Non c'è differenza qui (che io conosca). .clickè semplicemente un metodo di convenienza / aiuto per.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);

Questo è molto diverso, in quanto .liveaggiunge eventi al selettore in cui si passa (che non è stato qui) e continua a guardare il DOM man mano che i nodi vengono inseriti / rimossi

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

Questo è diverso solo per il modo in cui stai assegnando i gestori di eventi. .delegateè incentrato sul gorgoglio di eventi DOM. Il principio di base è che ogni evento bolle attraverso l'albero DOM fino a raggiungere l'elemento radice ( documento windowo <html>o <body>, non ricordo esattamente).

Ad ogni modo, stai vincolando un onclickgestore a tutti gli <td>s all'interno $('#some_element')(devi specificare un selettore, anche se potresti dire $(document)). Quando si fa clic su uno dei suoi figli, l'evento si trasforma in <td>. È quindi possibile estrarre l'elemento di origine dell'evento (cosa che jQuery fa automaticamente per te).

Ciò è utile quando ci sono tonnellate di elementi e hai solo pochi (o un punto) centrale (s) che questi eventi passeranno. Ciò consente di risparmiare lo sforzo e la memoria del browser per consolidare questi gestori di eventi in meno oggetti.


1
.live() funziona anche dal gorgogliamento di eventi, in effetti .delegate()è un wrapper per .live(), sta solo aggiungendo un contesto e vincolando a un elemento diverso da quello documentdi catturare le bolle. Penso che la tua comprensione di come funzionano i gestori gorgoglianti sia un po 'fuori posto (questo è l'aspetto più comunemente frainteso di jQuery 1.4, credo). Il gestore si trova solo sull'elemento a cui lo hai associato, quindi qualsiasi elemento tu abbia richiamato .delegate(), o documentnel caso in .live()cui, quando un evento si sposta verso di esso, controlla il bersaglio per vedere se corrisponde al selettore e, in tal caso, viene eseguito.
Nick Craver
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.