jQuery: più di un gestore per lo stesso evento


137

Cosa succede se associo due gestori di eventi allo stesso evento per lo stesso elemento?

Per esempio:

var elem = $("...")
elem.click(...);
elem.click(...);

L'ultimo gestore "vince" o verranno eseguiti entrambi i gestori?

Risposte:


168

Verranno eseguiti entrambi i gestori, il modello di eventi jQuery consente più gestori su un elemento, quindi un gestore successivo non sostituisce un gestore precedente.

I gestori eseguiranno nell'ordine in cui erano vincolati .


1
cosa succede con il modo nativo? e come fa il nativo a sapere come rimuoverne uno specifico?
SuperUberDuper l'

1
Secondo DOM Level 3 (riferendosi alle specifiche HTML 5), i gestori di eventi vengono eseguiti nell'ordine in cui sono registrati - w3.org/TR/DOM-Level-3-Events/#event-phase e w3.org/TR/ 2014 / REC-html5-20141028 /… . I gestori di eventi possono essere rimossi passando un riferimento al gestore che è stato registrato
Russ Cam

@RussCam cosa succede se uno stesso gestore viene associato più di una volta, diciamo solo che jQuery('.btn').on('click',handlerClick);viene chiamato in vari punti senza effettivamente .off?
techie_28,

Si noti che per i widget widget di fabbrica jQueryUI, questo non è vero se si imposta il gestore come opzione. Per chiamare sia il vecchio che il nuovo gestore, è necessario utilizzare il bindmetodo Vedi questo per i dettagli: learn.jquery.com/jquery-ui/widget-factory/…
Michael Scheper,

@MichaelScheper sentiti libero di modificare la risposta e aggiornare con informazioni aggiuntive
Russ Cam

36

Si supponga di avere due gestori, f e g , e vuole fare in modo che essi vengono eseguiti in un ordine noto e fisso, poi basta incapsulare:

$("...").click(function(event){
  f(event);
  g(event);
});

In questo modo si ha (dal punto di vista jQuery) soltanto un conduttore, che chiama f e g nell'ordine specificato.


3
+1, l'incapsulamento all'interno di una funzione è la strada da percorrere. E una logica condizionale ancora migliore può essere contenuta all'interno della funzione del gestore per controllare gli eventi che vengono attivati.
Gordon Potter,

Una raccolta di gestori la cui sequenza è programmaticamente determinata.
Aaron Blenkush,

17

.bind () di jQuery si attiva nell'ordine in cui è stato associato :

Quando un evento raggiunge un elemento, vengono generati tutti i gestori associati a quel tipo di evento per l'elemento. Se sono presenti più gestori registrati, verranno sempre eseguiti nell'ordine in cui erano associati. Dopo l'esecuzione di tutti i gestori, l'evento continua lungo il normale percorso di propagazione dell'evento.

Fonte: http://api.jquery.com/bind/

Poiché le altre funzioni di jQuery (ad es. .click()) Sono scorciatoie .bind('click', handler), immagino che siano anche attivate nell'ordine in cui sono associate.


11

Dovresti essere in grado di utilizzare il concatenamento per eseguire gli eventi in sequenza, ad esempio:

$('#target')
  .bind('click',function(event) {
    alert('Hello!');
  })
  .bind('click',function(event) {
    alert('Hello again!');
  })
  .bind('click',function(event) {
    alert('Hello yet again!');
  });

Immagino che il codice seguente stia facendo lo stesso

$('#target')
      .click(function(event) {
        alert('Hello!');
      })
      .click(function(event) {
        alert('Hello again!');
      })
      .click(function(event) {
        alert('Hello yet again!');
      });

Fonte: http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

TFM dice anche:

Quando un evento raggiunge un elemento, vengono generati tutti i gestori associati a quel tipo di evento per l'elemento. Se sono presenti più gestori registrati, verranno sempre eseguiti nell'ordine in cui erano associati. Dopo l'esecuzione di tutti i gestori, l'evento continua lungo il normale percorso di propagazione dell'evento.


1
Né quel codice né quell'articolo definiscono un ordine di esecuzione del gestore. Sì, questo è l'ordine in cui si verificherà l' associazione di eventi , ma l'ordine che i gestori di eventi vengono chiamati è ancora ufficialmente indefinito.
Crescent Fresh,

ehh? che dire di "Ora quando si verifica l'evento click, verrà chiamato il primo gestore di eventi, seguito dal secondo, seguito dal terzo". non è chiaro?
anddoutoi,

e sì, so che le registrazioni ufficiali non lo definiscono e PPK ha già dimostrato che l'esecuzione dell'evento è casuale ma forse jQuery ha risolto questo ^^
anddoutoi,

Ah, ho perso quella frase. In effetti, l'autore è male informato. jQuery non ha "risolto" questo. Poiché le specifiche non definiscono formalmente l'ordine, tecnicamente nulla deve essere riparato.
Crescent Fresh,

5
@CrescentFresh: mi dispiace per una risposta così tardiva, ho appena visto la domanda, ma vorrei che tu When an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound. After all handlers have executed, the event continues along the normal event propagation path.
indicassi il

2

Entrambi i gestori vengono chiamati.

Potresti pensare al binding di eventi inline (ad esempio "onclick=..."), dove un grande svantaggio è che solo un gestore può essere impostato per un evento.

jQuery è conforme al modello di registrazione eventi DOM livello 2 :

Il modello di eventi DOM consente la registrazione di più listener di eventi su un singolo EventTarget. A tale scopo, i listener di eventi non vengono più archiviati come valori di attributo


@Rich: l'ordine è ufficialmente indefinito.
Crescent Fresh,

2

Ha funzionato con successo utilizzando i 2 metodi: l'incapsulamento di Stephan202 e i listener di eventi multipli. Ho 3 schede di ricerca, definiamo i loro ID di testo di input in un array:

var ids = new Array("searchtab1", "searchtab2", "searchtab3");

Quando il contenuto di searchtab1 cambia, voglio aggiornare searchtab2 e searchtab3. Ha fatto così per l'incapsulamento:

for (var i in ids) {
    $("#" + ids[i]).change(function() {
        for (var j in ids) {
            if (this != ids[j]) {
                $("#" + ids[j]).val($(this).val());
            }
        }
    });
}

Listener di eventi multipli:

for (var i in ids) {
    for (var j in ids) {
        if (ids[i] != ids[j]) {
            $("#" + ids[i]).change(function() {
                $("#" + ids[j]).val($(this).val());
            });
        }
    }
}

Mi piacciono entrambi i metodi, ma il programmatore ha scelto l'incapsulamento, tuttavia anche i listener di eventi multipli hanno funzionato. Abbiamo usato Chrome per testarlo.


1

Esiste una soluzione alternativa per garantire che un gestore si verifichi dopo l'altro: collegare il secondo gestore a un elemento contenente e lasciare che l'evento si riempia di bolle. Nel gestore collegato al contenitore, puoi guardare event.target e fare qualcosa se è quello a cui sei interessato.

Greggio, forse, ma sicuramente dovrebbe funzionare.


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.