Différence entre les fonctions jQuery `click`,` bind`, `live`,` delegate`, `trigger` et` on` (avec un exemple)?

139

J'ai lu la documentation de chaque fonction sur jQuery official website, mais il n'y a pas de listes de comparaison entre les fonctions ci-dessous:

$().click(fn)
$().bind('click',fn)
$().live('click',fn)
$().delegate(selector, 'click', fn)
$().trigger('click') // UPDATED
$().on('click', selector ,fn); // more UPDATED

Veuillez éviter tout lien de référence.

Comment fonctionnent exactement toutes les fonctions ci-dessus et lesquelles doivent être préférées dans quelle situation?

Remarque: s'il existe d'autres fonctions ayant la même fonctionnalité ou le même mécanisme, veuillez préciser.

Mettre à jour

J'ai également vu une $.triggerfonction. Cela fonctionne-t-il de la même manière que les fonctions ci-dessus?

Plus de mise à jour

Maintenant .onest ajouté dans la v1.7 et je pense que celui-ci couvre en quelque sorte toutes les fonctions ci-dessus.

diEcho
la source
3
@I Comme PHP, parfois les gens votent contre des choses s'ils ne pensent pas que c'est une question à laquelle un manuel ne peut pas répondre ou qui semble être une question de devoir. ne vous inquiétez pas, d'autres personnes voteront si elles le trouvent utile.
typeoneerror
@ Typeoneerror - Merci pour le soutien, j'ai déjà lu le manuel et quand je n'ai pas compris la différence claire, je poste ici.
diEcho
3
@J'aime PHP - J'ai modifié la question pour un peu de nettoyage ... cela est souvent posé mais rarement de cette manière, cela peut facilement être une ressource précieuse pour google. Je suis d'accord qu'une entrée wiki-ish de quelque chose comme ça serait très utile, je vois de la confusion à ce sujet, en particulier avec .live()et .delegate()presque tous les jours, +1 pour une question parfaitement valide.
Nick Craver
@Nick Craver Merci d'avoir édité, en fait je suis mauvais en anglais (lol). y a-t-il un maunal / référence sur lequel comment publier une question SO. ot il vient juste par expérience
diEcho
@J'aime PHP - C'est un peu des deux, il y a une excellente FAQ complète pour SO ici: meta.stackexchange.com/questions/7931 Pour le phrasé / commentaires, vous commencez simplement à apprendre ce qui convient et c'est le meilleur moyen de Transmettez vos pensées, code> n'importe quelle description parfois, en utilisant le bon mot-clé, en étiquetant de manière appropriée, plus vous êtes ici, je suppose, je vois beaucoup d'affiches s'améliorer avec le temps. Quant à votre modification, .trigger()invoque simplement le gestionnaire d'événements ... J'ajouterai une description à ma réponse ci-dessous.
Nick Craver

Réponses:

162

Avant de lire ceci, tirez cette liste d'événements sur une autre page, l'API elle-même est extrêmement utile et tout ce dont je parle ci-dessous est directement lié à cette page .

Tout d'abord, .click(function)c'est littéralement un raccourci pour .bind('click', function), ils sont équivalents. Utilisez-les lors de la liaison d'un gestionnaire directement à un élément , comme ceci:

$(document).click(function() {
  alert("You clicked somewhere in the page, it bubbled to document");
});

Si cet élément est remplacé ou jeté, ce gestionnaire ne sera plus là. De plus, les éléments qui n'étaient pas là lorsque ce code a été exécuté pour attacher le gestionnaire (par exemple, le sélecteur l'a trouvé alors) n'obtiendront pas le gestionnaire.

.live()et .delegate()sont similaires, .delegate()utilisent en fait en .live()interne, ils écoutent tous les deux les événements à bouillir. Cela fonctionne pour les éléments nouveaux et anciens , ils font des bulles d'événements de la même manière. Vous les utilisez lorsque vos éléments peuvent changer, par exemple en ajoutant de nouvelles lignes, des éléments de liste, etc. Si vous n'avez pas de parent / ancêtre commun qui restera dans la page et ne sera remplacé à aucun moment, utilisez .live(), comme ceci:

$(".clickAlert").live('click', function() {
  alert("A click happened");
});

Si toutefois vous avez un élément parent quelque part qui n'est pas remplacé (donc ses gestionnaires d'événements ne vont pas bye bye), vous devriez le gérer .delegate(), comme ceci:

$("#commonParent").delegate('.clickAlert', 'click', function() {
  alert("A click happened, it was captured at #commonParent and this alert ran");
});

Cela fonctionne presque de la même manière que .live(), mais l'événement bouillonne moins de fois avant d'être capturé et les gestionnaires exécutés. Une autre utilisation courante de ces deux méthodes est que votre classe change sur un élément, ne correspondant plus au sélecteur que vous avez utilisé à l'origine ... avec ces méthodes, le sélecteur est évalué au moment de l'événement , s'il correspond, le gestionnaire s'exécute. .so l'élément qui ne correspond plus au sélecteur compte, il ne s'exécutera plus. Avec .click()toutefois, le gestionnaire d'événements est droit lié à l'élément DOM, le fait qu'il ne correspond pas à ce que le sélecteur a été utilisé pour trouver est hors de propos ... l'événement est lié et il va rester jusqu'à cet élément est parti, ou le gestionnaire est supprimé via .unbind().

Encore une autre utilisation courante pour .live()et .delegate()est la performance . Si vous avez affaire à de nombreux éléments, attacher un gestionnaire de clics directement à chaque élément est coûteux et prend du temps. Dans ces cas, il est plus économique de configurer un seul gestionnaire et de laisser le bullage faire le travail, jetez un œil à cette question où cela a fait une énorme différence , c'est un bon exemple de l'application.


Déclenchement - pour la question mise à jour

Il y a 2 principales fonctions de déclenchement de gestionnaire d'événements disponibles, elles appartiennent à la même catégorie "Event Handler Attachment" dans l'API , ce sont .trigger()et .triggerHandler(). .trigger('eventName')a quelques raccourcis intégrés pour les événements courants, par exemple:

$().click(fn); //binds an event handler to the click event
$().click();   //fires all click event handlers for this element, in order bound

Vous pouvez voir une liste comprenant ces raccourcis ici .

Quant à la différence, .trigger()déclenche le gestionnaire d'événements (mais pas l'action par défaut la plupart du temps, par exemple en plaçant le curseur au bon endroit dans un clic <textarea>). Cela provoque les gestionnaires d'événements dans l'ordre dans lequel ils ont été liés (comme le ferait l'événement natif), déclenche les actions d'événement natif et fait remonter le DOM.

.triggerHandler()est généralement dans un but différent, ici vous essayez juste de déclencher le (s) gestionnaire (s) lié (s), cela ne provoque pas le déclenchement de l'événement natif, par exemple la soumission d'un formulaire. Il ne fait pas de bulles dans le DOM et n'est pas chaînable (il renvoie tout ce que le dernier gestionnaire d'événements lié pour cet événement renvoie). Par exemple, si vous vouliez déclencher un focusévénement mais ne pas focaliser réellement l'objet, vous voulez juste que le code avec .focus(fn)lequel vous êtes lié s'exécute, cela le ferait, alors que le .trigger()ferait aussi bien que concentrer l'élément et faire des bulles.

Voici un exemple du monde réel:

$("form").submit(); //actually calling `.trigger('submit');`

Cela exécutera tous les gestionnaires de soumission, par exemple le plugin de validation jQuery , puis essaiera de soumettre le fichier <form>. Cependant, si vous vouliez simplement valider, puisqu'il est connecté via un submitgestionnaire d'événements, mais pas soumettre <form>ensuite, vous pouvez utiliser .triggerHandler('submit'), comme ceci:

$("form").triggerHandler('submit');

Le plugin empêche le gestionnaire de soumettre le formulaire en bombardant si le contrôle de validation échoue, mais avec cette méthode, nous ne nous soucions pas de ce qu'il fait. Que ce soit avorté ou non nous ne sommes pas essayer de soumettre le formulaire, nous voulions juste déclencher revalider et ne rien faire d' autre. ( Avertissement: c'est un exemple superflu car il y a une .validate()méthode dans le plugin, mais c'est une bonne illustration de l'intention)

Nick Craver
la source
Très minutieux. Une petite correction: triggerne déclenche pas d'événement natif. Par natif, j'entends un événement simulé avec fireEvent(IE) ou dispatchEvent(w3c).
Crescent Fresh le
@Crescent - Mis à jour pour être moins ambigu, je voulais dire qu'il déclenche les actions d' événement natives , comme la soumission de formulaires, le suivi des liens, etc ... j'espère que la mise à jour est plus claire :)
Nick Craver
@Nick d'après ce que je lis, il semble que votre opinion live()soit différente de celle que vous m'avez donnée ici: stackoverflow.com/questions/3981762/... Le «poids» est-il toujours un problème lors de l'utilisation live()?
Yahel du
@yahelc - Oui, bien sûr ... cette réponse compare strictement les options des gestionnaires d'événements et leur objectif spécifique. Le coût du poids par rapport au nombre de liaisons initiales par rapport à l'ajout dynamique de quelque chose par rapport au sélecteur initial sont tous des préoccupations toujours valables. Si vous êtes la structure de page n'est pas que grand que vous vous n'avez pas que beaucoup d' événements alors vous êtes bien ... l'inquiétude suscitée par le poids est directement proportionnelle à la taille / profondeur de votre structure et le nombre d'événements (de le type que votre .live()appel écoute, par exemple click) qui sont générés, car il exécute des sélecteurs pour chacun d'eux.
Nick Craver
1
dans jQuery 1.7, live () est obsolète au profit de $ (document) .on ().
Synchro
28

Les deux premiers sont équivalents.

// The following two statements do the same thing:
$("blah").click( function() { alert( "Click!" ); } );
$("blah").bind( "click", function() { alert( "Click!" ); } ); 

Le second, cependant, peut être utilisé pour se lier à plus d'un événement en même temps, en spécifiant plusieurs noms d'événements séparés par des espaces:

$("blah").bind( "click mouseover mouseout", function() { alert( "Click! Or maybe mouse moved." ); } ); 

La .liveméthode est plus intéressante. Prenons l'exemple suivant:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").click( function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

Après l'exécution de la deuxième ligne du script, le deuxième lien aura également une classe CSS «myLink». Mais il n'aura pas le gestionnaire d'événements, car il n'avait pas la classe lorsque l'événement a été attaché.

Considérez maintenant que vous vouliez que ce soit l'inverse: chaque fois qu'un lien avec la classe "myLink" apparaît quelque part sur la page, vous voulez qu'il ait automatiquement le même gestionnaire d'événements. Ceci est très courant lorsque vous avez des types de listes ou de tableaux, dans lesquels vous ajoutez des lignes ou des cellules de manière dynamique, mais que vous voulez qu'ils se comportent tous de la même manière. Au lieu de vous efforcer d'assigner à nouveau des gestionnaires d'événements à chaque fois, vous pouvez utiliser la .liveméthode:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").live( "click", function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

Dans cet exemple, le deuxième lien obtiendra également le gestionnaire d'événements dès qu'il obtient la classe "myLink". La magie! :-)

Bien sûr, ce n'est pas si littéral. Ce .livequi fait vraiment est d'attacher le gestionnaire non pas à l'élément spécifié lui-même, mais à la racine même de l'arborescence HTML (l'élément "body"). Les événements en DHTML ont cette caractéristique amusante de "bouillonnement". Considère ceci:

<div> <a> <b>text</b> </a> </div>

Si vous cliquez sur "texte", alors l'élément <b> recevra d'abord un événement "clic". Après cela, l'élément <a> recevra un événement "clic". Et après cela, l'élément <div> recevra un événement "click". Et ainsi de suite - jusqu'à l'élément <body>. Et c'est là que jQuery attrapera l'événement et verra s'il y a des gestionnaires "en direct" qui s'appliquent à l'élément qui a causé l'événement en premier lieu. Soigné!

Et enfin, la .delegateméthode. Il prend simplement tous les enfants de votre élément qui se conforment au sélecteur donné et leur attache un gestionnaire "live". Regarde:

$("table").delegate( "td", "click", function() { alert( "Click!" ); } );

// Is equivalent to:
$("table").each( function() {
    $(this).find( "td" ).live( "click", function() { alert( "Click!" ); } );
} );

Des questions?

Fyodor Soikin
la source
Pour être précis, .live()se lie à documentpas <body>:) Vous pouvez voir une démo ici, il suffit de tirer la console pour inspecter: jsfiddle.net/aJy2B
Nick Craver
3
Il était plus pratique de l'expliquer de cette façon. :-)
Fyodor Soikin
4
Assez juste sur la partie "body", mais "tout le chemin jusqu'à l'élément <body>" est faux, les événements continuent à bouillonner là-bas, et ce n'est pas là où .live()vivent les gestionnaires, c'est au-dessus, sur document:) Vous pouvez voir un démo de ceci ici: jsfiddle.net/S2VBX
Nick Craver
8

Depuis jQuery 1.7, la méthode .live () était obsolète. Si vous utilisez une version de jQuery <1.7, il est officiellement recommandé d'utiliser .delegate () sur .live ().

.live () a maintenant été remplacé par .on ().

Il est préférable d'aller directement sur le site jQuery pour plus d'informations, mais voici les versions actuelles de la méthode .on ():

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

http://api.jquery.com/on/

Jonathan Tonge
la source
2

$().click(fn)et $().bind('click', fn)sont identiques à première vue, mais la $.bindversion est plus puissante pour deux raisons:

  1. $().bind()vous permet d'affecter un gestionnaire à plusieurs événements, par exemple $().bind('click keyup', fn),.
  2. $().bind()prend en charge les événements avec espace de nom - une fonctionnalité puissante si vous souhaitez supprimer (dissocier) uniquement certains gestionnaires d'événements auxquels un élément est lié - en savoir plus dans Evénements avec espace de nom .

Live vs délégué: cela a déjà été répondu dans les autres réponses.

fbuchinger
la source
1

C'est là que la lecture de l'API peut aider. Cependant, je sais par cœur, donc vous pouvez continuer à être paresseux (yay!).

$('#something').click(fn);
$('#something').bind('click',fn);

Il n'y a aucune différence ici (que je sache). .clickest simplement une méthode pratique / d'aide pour.bind('click'

// even after this is called, all <a>s in
// <div class="dynamic_els"> will continue
// to be assigned these event handlers

$('div.dynamic_els a').live(‘click’,fn);

Ceci est très différent, car .liveajoute des événements au sélecteur que vous passez (ce que vous n'avez pas ici) et continue de regarder le DOM lorsque des nœuds sont insérés / supprimés

$('#some_element').delegate('td','click',fn);

Ceci n'est différent qu'en raison de la façon dont vous affectez les gestionnaires d'événements. .delegateest centré sur le bouillonnement d'événements DOM. Le principe de base est que chaque événement monte dans l'arborescence DOM jusqu'à ce qu'il atteigne l'élément racine ( documentou windowou <html>ou <body>, je ne me souviens plus exactement).

Dans tous les cas, vous liez un onclickgestionnaire à tous les <td>s $('#some_element')(vous devez spécifier un sélecteur, bien que vous puissiez dire $(document)). Lorsqu'on clique sur l'un de ses enfants, l'événement remonte jusqu'au <td>. Vous pouvez ensuite extraire l'élément source de l'événement (ce que jQuery fait pour vous automatiquement).

Ceci est utile quand il y a des tonnes d'éléments et que vous n'avez que quelques points (ou un point central) par lesquels ces événements vont passer. Cela économise les efforts et la mémoire du navigateur pour consolider ces gestionnaires d'événements en moins d'objets.

Dan Beam
la source
1
.live() fonctionne également avec le bullage d'événement, en fait .delegate()est un wrapper pour .live(), il s'agit simplement d'ajouter un contexte et une liaison à un élément autre que documentpour capturer les bulles. Je pense que votre compréhension du fonctionnement des gestionnaires bouillonnants est un peu décevante (c'est l'aspect le plus souvent mal compris de jQuery 1.4 je pense). Le gestionnaire se trouve uniquement sur l'élément auquel vous l'avez lié, donc quel que soit l'élément .delegate()sur lequel vous avez appelé , ou documentdans le cas .live()où un événement s'y trouve, il vérifie la cible pour voir si elle correspond au sélecteur, et si c'est le cas, s'exécute.
Nick Craver