jQuery: plusieurs gestionnaires pour le même événement


137

Que se passe-t-il si je lie deux gestionnaires d'événements au même événement pour le même élément?

Par exemple:

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

Le dernier gestionnaire "gagne" ou les deux gestionnaires seront-ils exécutés?

Réponses:


168

Les deux gestionnaires s'exécuteront, le modèle d'événement jQuery autorise plusieurs gestionnaires sur un élément, par conséquent, un gestionnaire plus récent ne remplace pas un gestionnaire plus ancien.

Les gestionnaires s'exécuteront dans l'ordre dans lequel ils ont été liés .


1
que se passe-t-il avec la manière native? et comment le natif sait-il comment en supprimer un en particulier?
SuperUberDuper

1
Selon le DOM niveau 3 (faisant référence à la spécification HTML 5), les gestionnaires d'événements sont exécutés dans l'ordre dans lequel ils sont enregistrés - w3.org/TR/DOM-Level-3-Events/#event-phase et w3.org/TR/ 2014 / REC-html5-20141028 /… . Les gestionnaires d'événements peuvent être supprimés en passant une référence au gestionnaire qui a été enregistré
Russ Cam

@RussCam que se passe-t-il si un même gestionnaire est lié plus d'une fois, disons simplement qu'il jQuery('.btn').on('click',handlerClick);est appelé à divers endroits sans .offqu'il soit réellement nécessaire?
techie_28

Notez que pour les widgets widgetfactory jQueryUI, ce n'est pas vrai si vous définissez le gestionnaire comme option. Pour que l'ancien et le nouveau gestionnaire soient appelés, vous devez utiliser la bindméthode. Voir ceci pour plus de détails: learn.jquery.com/jquery-ui/widget-factory/…
Michael Scheper

@MichaelScheper, n'hésitez pas à modifier la réponse et à mettre à jour avec des informations supplémentaires
Russ Cam

36

Supposons que vous ayez deux gestionnaires, f et g , et que vous souhaitiez vous assurer qu'ils sont exécutés dans un ordre connu et fixe, puis encapsulez-les simplement:

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

De cette façon, il n'y a (du point de vue de jQuery) qu'un seul gestionnaire, qui appelle f et g dans l'ordre spécifié.


3
+1, l'encapsulation à l'intérieur d'une fonction est la voie à suivre. Et une logique conditionnelle encore meilleure peut être contenue dans la fonction de gestionnaire pour contrôler le ou les événements qui sont déclenchés.
Gordon Potter du

Collection de gestionnaires dont la séquence est déterminée par programme.
Aaron Blenkush

17

.bind () de jQuery se déclenche dans l'ordre dans lequel il a été lié :

Lorsqu'un événement atteint un élément, tous les gestionnaires liés à ce type d'événement pour l'élément sont déclenchés. S'il y a plusieurs gestionnaires enregistrés, ils s'exécuteront toujours dans l'ordre dans lequel ils ont été liés. Une fois tous les gestionnaires exécutés, l'événement continue le long du chemin de propagation d'événement normal.

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

Parce que les autres fonctions de jQuery (par exemple .click()) sont des raccourcis pour .bind('click', handler), je suppose qu'elles sont également déclenchées dans l'ordre dans lequel elles sont liées.


11

Vous devriez pouvoir utiliser le chaînage pour exécuter les événements dans l'ordre, par exemple:

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

Je suppose que le code ci-dessous fait la même chose

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

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

TFM dit également:

Lorsqu'un événement atteint un élément, tous les gestionnaires liés à ce type d'événement pour l'élément sont déclenchés. S'il y a plusieurs gestionnaires enregistrés, ils s'exécuteront toujours dans l'ordre dans lequel ils ont été liés. Une fois tous les gestionnaires exécutés, l'événement continue le long du chemin de propagation d'événement normal.


1
Ni ce code ni cet article ne définissent un ordre d'exécution du gestionnaire. Oui, c'est l'ordre dans lequel la liaison d' événements se produira, mais l'ordre dans lequel les gestionnaires d'événements sont appelés n'est toujours pas officiellement défini.
Crescent Fresh le

hein? que dire de "Maintenant, lorsque l'événement de clic se produit, le premier gestionnaire d'événements sera appelé, suivi du second, suivi du troisième." ne sait pas?
anddoutoi

et oui, je sais que les recs officiels ne définissent pas cela et PPK a déjà prouvé que l'exécution de l'événement est aléatoire mais peut-être que jQuery a corrigé cela ^^
anddoutoi

Ahh, j'ai raté cette phrase. En fait, l'auteur est mal informé. jQuery n'a pas "corrigé" cela. Parce que la spécification ne définit pas formellement la commande, techniquement rien n'a besoin d'être corrigé.
Crescent Fresh le

5
@CrescentFresh: Désolé pour une réponse aussi tardive, je viens de voir la question, mais j'aimerais que vous 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.
pointiez

2

Les deux gestionnaires sont appelés.

Vous pensez peut-être à la liaison d'événement en ligne (par exemple "onclick=..."), où un gros inconvénient est qu'un seul gestionnaire peut être défini pour un événement.

jQuery est conforme au modèle d'enregistrement d'événement DOM Niveau 2 :

Le modèle d'événement DOM permet l'enregistrement de plusieurs écouteurs d'événements sur un seul EventTarget. Pour ce faire, les écouteurs d'événements ne sont plus stockés en tant que valeurs d'attribut


@Rich: la commande est officiellement indéfinie.
Crescent Fresh le

2

Cela a fonctionné avec succès en utilisant les 2 méthodes: l'encapsulation de Stephan202 et plusieurs écouteurs d'événements. J'ai 3 onglets de recherche, définissons leurs identifiants de texte d'entrée dans un tableau:

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

Lorsque le contenu de searchtab1 change, je souhaite mettre à jour searchtab2 et searchtab3. Je l'ai fait de cette façon pour l'encapsulation:

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

Écouteurs d'événements multiples:

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

J'aime les deux méthodes, mais le programmeur a choisi l'encapsulation, mais plusieurs écouteurs d'événements fonctionnaient également. Nous avons utilisé Chrome pour le tester.


1

Il existe une solution de contournement pour garantir qu'un gestionnaire se produit après l'autre: attachez le deuxième gestionnaire à un élément conteneur et laissez l'événement remonter. Dans le gestionnaire attaché au conteneur, vous pouvez consulter event.target et faire quelque chose si c'est celui qui vous intéresse.

Brut, peut-être, mais cela devrait vraiment fonctionner.


0

jquery exécutera les deux gestionnaires car il autorise plusieurs gestionnaires d'événements. J'ai créé un exemple de code. Tu peux l'essayer

démo

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.