Direct vs. Delegated – jQuery .on ()

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

Lorsqu'un selector est fourni, le gestionnaire d'événements est désigné comme 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 éclaire l'événement de la cible de l'événement jusqu'à l'élément où le gestionnaire est attaché (c'est-à-dire l'élément le plus à l'extrême) et exécute le gestionnaire pour tous les éléments le long de ce chemin correspondant au sélecteur.

Qu'est-ce que cela signifie par "exécute le gestionnaire pour tous les éléments"? J'ai fait une 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 autre exemple pour clarifier ce point? Merci.

Cas 1 (direct):

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

== Hey! Je veux que chaque span.green à l'intérieur de div # cible pour écouter: lorsque vous cliquez dessus, faites X.

Affaire 2 (délégué):

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

== Hey, div # target! Lorsque l'un de vos éléments enfants qui sont "span.green" est cliqué, faites X avec eux.

En d'autres termes…

Dans le cas 1, chacun de ces délais a été donné individuellement des instructions. Si de nouvelles versions sont créées, elles n'auraient pas entendu les instructions et ne répondront pas aux clics. Chaque portée est directement responsable de ses propres événements.

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

La première façon, $("div#target span.green").on() , lie un gestionnaire de clics directement à la (les) plage (s) qui correspond au sélecteur au moment où ce code est exécuté. Cela signifie que si d'autres spans sont ajoutés plus tard (ou leur classe a changé pour correspondre), ils ont manqué et n'aura pas de gestionnaire de clics. Cela signifie également que si vous retirez plus tard la classe "verte" de l'une des extensions, son gestionnaire de clics continuera à s'exécuter – jQuery ne surveille pas comment 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, c'est contre ceux qui correspondent à ce moment-là), mais lorsqu'un clic se produit quelque part dans La fonction div la fonction de gestionnaire ne sera exécutée que si le clic s'est produit non seulement dans le div, mais dans un élément enfant correspondant au sélecteur dans le second paramètre à .on() , "span.green". Fait de cette façon, cela n'a pas d'importance lorsque ces durées d'enfant ont été créées, en cliquant dessus continuera le gestionnaire.

Donc, pour une page qui n'ajoute pas de façon dynamique ni ne modifie son contenu, vous ne remarquerez pas une différence entre les deux méthodes. Si vous ajoutez dynamiquement des éléments enfants supplémentaires, la deuxième syntaxe signifie que vous ne devez pas vous soucier de vous assigner des gestionnaires de clics parce que vous l'avez déjà fait une fois sur le parent.

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

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

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

J'ai publié une publication avec la comparaison des événements directs et délégué. Je compare pure js mais il a la même signification pour jquery qui ne l'encapsule que.

La conclusion est que la gestion des événements délégués est destinée à la structure DOM dynamique où les éléments liés peuvent être créés pendant que l'utilisateur interagit avec la page (sans besoin de nouvelles liaisons) et la gestion directe des événements est pour les éléments statiques DOM, lorsque nous savons que la structure ne changera pas.

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

L'utilisation de gestionnaires toujours délégués, ce que je vois est courant, à la mode, n'est pas la bonne façon, de nombreux programmeurs l'utilisent parce que "cela devrait être utilisé", mais la vérité est que les gestionnaires d'événements directs sont mieux pour une situation et le choix dont l'utilisation de la méthode devrait être prise en charge par Connaissance des différences.

Tangentiel à l'OP, mais le concept qui m'a aidé à démêler la confusion avec cette fonctionnalité est que les éléments liés doivent être parents des éléments sélectionnés .

  • Lié se réfère à ce qui reste du .on .
  • Selected se réfère 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 s'applique uniquement à des é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 suggère "des éléments 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 contrôle de pourquoi délégué .on ne fonctionne pas

Des raisons trompeuses 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 un enfant approprié d'un élément lié. C'est le même élément.
  3. L'élément sélectionné a empêché de faire bouillonner un événement à l'élément lié en appelant .stopPropagation() .

(Omettre des raisons moins difficiles, comme un sélecteur mal orthographié.)