web-dev-qa-db-fra.com

Tous les événements jquery doivent-ils être liés à $ (document)?

D'où ça vient

Lorsque j'ai appris jQuery pour la première fois, j’attachais normalement des événements comme celui-ci:

$('.my-widget a').click(function() {
    $(this).toggleClass('active');
});

Après en savoir plus sur la vitesse de sélection et la délégation d'événements, j'ai lu à plusieurs reprises que "la délégation d'événements jQuery rendra votre code plus rapide". Alors j'ai commencé à écrire du code comme ceci:

$('.my-widget').on('click','a',function() {
    $(this).toggleClass('active');
});

C'était également le moyen recommandé de répliquer le comportement de l'événement obsolète .live (). Ce qui est important pour moi, car bon nombre de mes sites ajoutent/suppriment dynamiquement des widgets tout le temps. Ce qui précède ne se comporte cependant pas exactement comme .live (), car seuls les éléments ajoutés au conteneur existant. 'Mon-widget' auront le comportement. Si j'ajoute dynamiquement un autre bloc de code html une fois le code exécuté, ces événements ne seront pas associés aux événements. Comme ça:

setTimeout(function() {
    $('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);


Ce que je veux réaliser:

  1. l'ancien comportement de .live () // signifiant attacher des événements à des éléments non encore existants
  2. les avantages de .on ()
  3. performance la plus rapide pour lier des événements
  4. Un moyen simple de gérer des événements

J'attache maintenant tous les événements comme celui-ci:

$(document).on('click.my-widget-namespace', '.my-widget a', function() {
    $(this).toggleClass('active');
});

Ce qui semble répondre à tous mes objectifs. (Oui, c'est plus lent dans IE pour une raison quelconque, aucune idée de pourquoi?) C'est rapide, car un seul événement est lié à un élément singulier et le sélecteur secondaire n'est évalué que lorsque l'événement se produit (veuillez corrigez-moi si cela est faux ici). L'espace de noms est génial puisqu'il facilite le basculement de l'écouteur d'événements.

Ma solution/question

Je commence donc à penser que les événements jQuery devraient toujours être liés à $ (document).
Y a-t-il une raison pour laquelle vous ne voudriez pas faire cela?
Cela pourrait-il être considéré comme une pratique exemplaire? Si non, pourquoi?

Si vous avez tout lu, merci. J'apprécie tout/tous les commentaires/idées.

Hypothèses:

  1. Utilisation de jQuery prenant en charge .on() // au moins la version 1.7
  2. Vous voulez que l'événement soit ajouté au contenu ajouté dynamiquement

Lectures/Exemples:

  1. http://24ways.org/2011/your-jquery-now-with-less-suck
  2. http://brandonaaron.net/blog/2010/03/4/event-delegation-with-jquery
  3. http://www.jasonbuckboyer.com/playground/speed/speed.html
  4. http://api.jquery.com/on/
155
Buck

Non - vous ne devez PAS lier tous les gestionnaires d'événements délégués à l'objet document. C'est probablement le pire scénario que vous puissiez créer.

Tout d'abord, la délégation d'événements ne rend pas toujours votre code plus rapide. Dans certains cas, c'est avantageux et dans d'autres, non. Vous devez utiliser la délégation d'événements lorsque vous en avez réellement besoin et lorsque vous en bénéficiez. Sinon, vous devez lier les gestionnaires d'événements directement aux objets sur lesquels l'événement se produit, ce qui sera généralement plus efficace.

Deuxièmement, vous ne devriez PAS lier tous les événements délégués au niveau du document. C’est exactement pour cette raison que .live() est déconseillé car c’est très inefficace lorsque de nombreux événements sont liés de cette façon. Pour la gestion des événements délégués, il est BEAUCOUP plus efficace de les lier au parent le plus proche qui n’est pas dynamique.

Troisièmement, tous les événements ne fonctionnent pas et tous les problèmes ne peuvent pas être résolus par délégation. Par exemple, si vous souhaitez intercepter des événements clés sur un contrôle de saisie et empêcher la saisie de clés non valides dans le contrôle de saisie, vous ne pouvez pas le faire avec la gestion des événements délégués car, au moment où l'événement se propage jusqu'au gestionnaire délégué, il a déjà été traité par le contrôle d’entrée et il est trop tard pour influencer ce comportement.

Voici des moments où la délégation d'événements est requise ou avantageuse:

  • Lorsque les objets sur lesquels vous capturez des événements sont créés/supprimés de manière dynamique et que vous souhaitez toujours les capturer sans avoir à relier explicitement les gestionnaires d'événements à chaque fois que vous en créez un.
  • Lorsque vous avez beaucoup d'objets qui veulent tous le même gestionnaire d'événement (où lots est au moins des centaines). Dans ce cas, il peut s'avérer plus efficace au moment de la configuration de lier un gestionnaire d'événements délégué plutôt que des centaines ou plus de gestionnaires d'événements directs. Remarque: la gestion des événements délégués est toujours moins efficace au moment de l'exécution que les gestionnaires d'événements directs.
  • Lorsque vous essayez de capturer (à un niveau supérieur dans votre document) des événements qui se produisent sur n'importe quel élément du document.
  • Lorsque votre conception utilise explicitement l'événement bubbling et stopPropagation () pour résoudre un problème ou une fonctionnalité de votre page.

Pour comprendre cela un peu plus, il faut comprendre le fonctionnement des gestionnaires d'événements délégués de jQuery. Lorsque vous appelez quelque chose comme ceci:

$("#myParent").on('click', 'button.actionButton', myFn);

Il installe un gestionnaire d'événements générique jQuery sur l'objet #myParent. Lorsqu'un événement click clique sur ce gestionnaire d'événements délégué, jQuery doit parcourir la liste des gestionnaires d'événements délégués attachés à cet objet et voir si l'élément d'origine de l'événement correspond à l'un des sélecteurs des gestionnaires d'événements délégués.

Les sélecteurs pouvant être relativement impliqués, cela signifie que jQuery doit analyser chaque sélecteur, puis le comparer aux caractéristiques de la cible de l'événement d'origine pour voir si elle correspond à chaque sélecteur. Ce n'est pas une opération bon marché. Ce n'est pas grave s'il n'y en a qu'un, mais si vous placez tous vos sélecteurs sur l'objet document et que vous devez comparer des centaines de sélecteurs à chaque événement diffusé, cela peut sérieusement entraver les performances de gestion des événements.

Pour cette raison, vous souhaitez configurer vos gestionnaires d'événements délégués de manière à ce qu'un gestionnaire d'événements délégué soit aussi proche de l'objet cible que possible. Cela signifie que moins d’événements apparaîtront dans chaque gestionnaire d’événements délégué, améliorant ainsi les performances. Placer tous les événements délégués sur l'objet document est la pire performance possible, car tous les événements condensés doivent passer par tous les gestionnaires d'événements délégués et être évalués par rapport à tous les sélecteurs d'événements délégués possibles. C’est exactement pourquoi .live() est obsolète, car c’est ce que .live() a fait et cela s’est avéré très inefficace.


Donc, pour obtenir des performances optimisées:

  1. N'utilisez la gestion des événements délégués que si elle fournit réellement une fonctionnalité dont vous avez besoin ou améliore les performances. Ne l'utilisez pas toujours car c'est facile parce que vous n'en avez pas besoin. En réalité, sa performance est pire au moment de la distribution d'un événement que sa liaison directe.
  2. Associez autant que possible les gestionnaires d'événements délégués au parent le plus proche de la source de l'événement. Si vous utilisez la gestion déléguée des événements parce que vous souhaitez capturer des éléments dynamiques, sélectionnez le parent le plus proche qui n'est pas dynamique.
  3. Utilisez des sélecteurs faciles à évaluer pour les gestionnaires d’événements délégués. Si vous avez suivi le fonctionnement de la gestion des événements délégués, vous comprendrez qu'un gestionnaire d'événements délégué doit souvent être comparé à de nombreux objets. Vous devez donc sélectionner un sélecteur aussi efficace que possible ou ajouter des classes simples à vos objets pour pouvoir utiliser des sélecteurs plus simples. augmenter les performances de la gestion des événements délégués.
207
jfriend00

La délégation d'événements est une technique permettant d'écrire vos gestionnaires avant que l'élément n'existe réellement dans DOM. Cette méthode a ses propres inconvénients et ne devrait être utilisée que si vous avez de telles exigences.

Quand devriez-vous utiliser la délégation d'événements?

  1. Lorsque vous liez un gestionnaire commun à plusieurs éléments nécessitant les mêmes fonctionnalités. (Ex: survol de la ligne de la table)
    • Dans l'exemple, si vous deviez lier toutes les lignes à l'aide de la liaison directe, vous créeriez un gestionnaire n pour n lignes dans cette table. En utilisant la méthode de délégation, vous pourriez finir par gérer tous ceux qui se trouvent dans un seul gestionnaire.
  2. Lorsque vous ajoutez du contenu dynamique plus souvent dans DOM (Ex: Ajouter/supprimer des lignes d'un tableau)

Pourquoi ne devriez-vous pas utiliser la délégation d'événements?

  1. La délégation d'événements est plus lente que si vous liez l'événement directement à l'élément.
    • Il compare le sélecteur de cible sur chaque bulle touchée, la comparaison sera aussi coûteuse que compliquée.
  2. Aucun contrôle sur l'événement ne bouillonnant jusqu'à ce qu'il atteigne l'élément auquel il est lié.

PS: Même pour les contenus dynamiques, il n'est pas nécessaire d'utiliser la méthode de délégation d'événements si vous liez le gestionnaire une fois le contenu inséré dans DOM. (Si le contenu dynamique est ajouté pas fréquemment supprimé/ré-ajouté)

8

Apparemment, la délégation d'événements est actuellement recommandée. au moins pour Vanilla js.

https://gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-Vanilla-js/

"Performances Web # C’est comme si écouter chaque clic du document était mauvais pour la performance, mais c’est plus performant que d’avoir un groupe d’écouteurs d’événements sur des éléments individuels."

0
Reincha