web-dev-qa-db-fra.com

Direct vs délégué - jQuery .on ()

J'essaie de comprendre cette différence particulière entre les gestionnaires d'événements direct et délégués en utilisant le jQuery . On () méthode . Plus précisément, la dernière phrase de ce paragraphe:

Lorsqu'un selector est fourni, le gestionnaire d'événements est appelé délégué. Le gestionnaire n'est pas appelé lorsque l'événement se produit directement sur l'élément lié, mais uniquement pour les descendants (éléments internes) qui correspondent au sélecteur. jQuery met en événement l'événement de la cible d'événement jusqu'à l'élément auquel le gestionnaire est attaché (c'est-à-dire, l'élément le plus à l'intérieur) et exécute le gestionnaire pour tous les éléments le long de ce chemin correspondant au sélecteur.

Qu'entend-il par "exécute le gestionnaire pour tous les éléments"? J'ai fait un page de test pour expérimenter le concept. Mais les deux constructions suivantes conduisent au même comportement:

$("div#target span.green").on("click", function() {
   alert($(this).attr("class") + " is clicked");
});

ou,

$("div#target").on("click", "span.green", function() {
   alert($(this).attr("class") + " is clicked");
});

Peut-être que quelqu'un pourrait se référer à un exemple différent pour clarifier ce point? Merci.

152
moey

Cas 1 (direct):

$("div#target span.green").on("click", function() {...});

== Hé! Je veux que chaque span.green de div # target écoute: quand on clique dessus, on fait X.

Cas 2 (délégué):

$("div#target").on("click", "span.green", function() {...});

== Hé, div # cible! Lorsque vous cliquez sur un de vos éléments enfants "span.green", faites-le X avec eux.

En d'autres termes ...

Dans le cas 1, des instructions ont été données à chacune de ces plages. Si de nouvelles plages sont créées, ils n'auront pas entendu l'instruction et ne répondront pas aux clics. Chaque période est directement responsable pour ses propres événements.

Dans le cas 2, seul le conteneur a reçu l’instruction; il est responsable de la détection des clics au nom de ses éléments enfants. Le travail de capture d'événements a été délégué. Cela signifie également que l'instruction sera exécutée pour les éléments enfants créés à l'avenir.

364
N3dst4

La première façon, $("div#target span.green").on(), lie un gestionnaire de clics directement aux plages qui correspondent au sélecteur au moment de l'exécution du code. Cela signifie que si d'autres étendues sont ajoutées ultérieurement (ou si leur classe est modifiée pour correspondre), elles sont manquantes et ne disposent pas d'un gestionnaire de clics. Cela signifie également que si vous supprimez ultérieurement la classe "verte" de l'une des étendues, son gestionnaire de clics continuera à s'exécuter - jQuery ne garde pas trace de la façon dont le gestionnaire a été affecté et vérifie si le sélecteur correspond toujours.

La deuxième façon, $("div#target").on(), lie un gestionnaire de clics aux div (s) qui correspondent (encore une fois, ceci est opposé à ceux qui correspondent à ce moment-là), mais lorsqu'un clic survient quelque part dans le div, la fonction de gestionnaire ne sera exécuté que si le clic est survenu non seulement dans la div mais dans un élément enfant correspondant au sélecteur du deuxième paramètre à .on(), "span.green". Ainsi, peu importe le moment de la création de ces extensions d'enfant, cliquer sur celles-ci lancera toujours le gestionnaire.

Ainsi, pour une page qui n'ajoute ni ne modifie dynamiquement son contenu, vous ne remarquerez pas de différence entre les deux méthodes. Si vous ajoutez dynamiquement des éléments enfants supplémentaires, la deuxième syntaxe vous évite de leur attribuer des gestionnaires de clics, car vous l'avez déjà fait une fois pour le parent.

5
nnnnnn

L'explication de N3dst4 est parfaite. Sur cette base, nous pouvons supposer que tous les éléments enfants sont à l'intérieur du corps, nous devons donc utiliser uniquement ceci:

$('body').on('click', '.element', function(){
    alert('It works!')
});

Cela fonctionne avec un événement direct ou délégué.

4
Brynner Ferreira

Tangentielle au PO, mais le concept qui m'a aidé à dissiper toute confusion avec cette fonctionnalité est que les éléments liés doivent être les parents des éléments sélectionnés.

  • Bound fait référence à ce qui reste du .on.
  • Sélectionné fait référence au deuxième argument de .on().

La délégation ne fonctionne pas comme .find (), en sélectionnant un sous-ensemble des éléments liés. Le sélecteur ne s'applique qu'aux éléments enfants stricts.

$("span.green").on("click", ...

est très différent de

$("span").on("click", ".green", ...

En particulier, pour obtenir les avantages @ N3dst4 avec des "éléments qui seront créés à l'avenir", l'élément lié doit être un parent permanent. Ensuite, les enfants sélectionnés peuvent aller et venir.

MODIFIER

Liste de vérification des raisons pour lesquelles la délégation .on Ne fonctionne pas

Les raisons difficiles pour lesquelles $('.bound').on('event', '.selected', some_function) peuvent ne pas fonctionner:

  1. L'élément lié n'est pas permanent. Il a été créé après avoir appelé .on()
  2. L'élément sélectionné n'est pas une propriété propre enfant d'un élément lié. C'est le même élément.
  3. Élément sélectionné empêché bullage d'un événement à l'élément lié en appelant .stopPropagation().

(Omettre des raisons moins complexes, telles qu'un sélecteur mal orthographié.)

2
Bob Stein

Je rédige un article avec une comparaison des événements directs et délégués. Je compare js pur mais il a la même signification pour jquery qui l’encapsule seulement.

La conclusion est que la gestion des événements délégués concerne la structure DOM dynamique dans laquelle des éléments liés peuvent être créés tout en permettant à l'utilisateur d'interagir avec la page (plus besoin de liaisons), et la gestion directe des événements concerne des éléments DOM statiques, sachant que cette structure ne changera pas.

Pour plus d'informations et une comparaison complète - http://maciejsikora.com/standard-events-vs-event-delegation/

Utiliser des gestionnaires toujours délégués, ce qui, à mon avis, est très à la mode, n’est pas correct, beaucoup de programmeurs l’utilisent parce qu’il "devrait être utilisé", mais la vérité est que les gestionnaires d’événements directs sont meilleurs pour certaines situations et que le choix de la méthode à utiliser doit être pris en charge par la connaissance des différences.

1
Maciej Sikora