javascript - Problème d'activation et de désactivation de la liaison d'événement jQuery
迷茫
迷茫 2017-05-18 10:51:00
0
3
549

Le code est le suivant :

var $test = $(document);
  
function handler1() {
  console.log( "handler1" );
  $test.off( "click", handler2 );
}
  
function handler2() {
  console.log( "handler2" );
}
  
$test.on( "click", handler1 );
$test.on( "click", handler2 );

Pourquoi ce code affiche-t-il handler1 et handler2 lorsqu'il est cliqué pour la première fois ? Le off dans handler1 fonctionne mais handler2 est toujours exécuté une fois. Quelle est la raison ?
Référez-vous à la documentation jQuery

L'explication dans le document est la suivante : l'ajout ou la suppression de gestionnaires d'événements sur l'élément actuel ne prendra effet qu'à la prochaine gestion de l'événement
Peut-être que mon anglais est trop mauvais, j'ai l'impression que l'expression à cet endroit n'est pas très précise , ça devrait être L'ajout ou la suppression du même événement n'est pas valide lors du traitement en cours. Par exemple, j'ai modifié les deux clics comme suit

.
var $test = $(document);
  
function handler1() {
  console.log( "handler1" );
  $test.off( "mouseup", handler2 );
}
  
function handler2() {
  console.log( "handler2" );
}
  
$test.on( "mousedown", handler1 );
$test.on( "mouseup", handler2 );

Ensuite, seul handler1 sera affiché. On peut voir que la désactivation de mouseup dans mousedown est réussie

.

Retour au début, pourquoi l'ajout ou la suppression d'un même événement est invalide lors du traitement en cours ? (J'ai essayé de trouver le code source de jQuery, mais c'était assez compliqué, alors j'ai abandonné)

迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

répondre à tous(3)
左手右手慢动作

Il faut quand même partir du code source

Regardez ici d'abord : https://github.com/jquery/jqu...

handlerQueue = jQuery.event.handlers.call( this, event, handlers );

C'est le début du code de base pour la distribution d'événements.On peut voir que jquery doit appeler this.event.handler pour trouver la liste des rappels d'événements lors de la distribution d'événements Le handlerQueue ici n'est qu'une copie d'une partie. de la liste d'événements interne, et vous utilisez off pour la modifier. Il s'agit d'une liste d'événements interne et n'a aucun effet sur le handlerQueue copié.

C'est comme si toutes les fonctions de rappel d'événement étaient stockées dans le pot. Lorsqu'un événement se produit, jquery copiera un rappel, le placera dans le bol, puis exécutera les fonctions dans le bol dans l'ordre. Ce que vous modifiez en désactivant concerne uniquement la fonction dans le pot, et la fonction dans le bol n'est pas affectée.

左手右手慢动作

Vous pouvez considérer on comme l'ajout d'une méthode de traitement à un tableau de traitement d'événements du composant, et off comme la suppression de cette méthode du tableau. Lorsqu'un événement est déclenché, jq exécutera immédiatement les méthodes du tableau de traitement d'événements. Alors, que se passe-t-il si off est appelé dans la méthode de traitement d'événements ? Le document a clairement indiqué que la méthode de traitement ne sera pas immédiatement supprimée du tableau dans la boucle de déclenchement de l'événement en cours. Elle ne sera reflétée que lorsque l'événement lié sera à nouveau déclenché.

Peter_Zhu

Merci à tous
Le problème a été trouvé. La raison est que lorsque jq encapsule en interne des événements, les événements du même type seront ajoutés au même tableau, et lorsque l'événement est déclenché, le parcours est une copie de ce tableau. Off ne modifie pas la copie, donc Hanler2 est affiché lorsque vous cliquez pour la première fois. Quant à mousedown et mouseup, car ce sont des types d'événements différents, ils sont encapsulés dans deux tableaux, il est donc efficace de désactiver mouseup dans. souris vers le bas. Peut-être que l'expression n'est pas très bonne, veuillez poster quelques lignes du code source principal de jq

//获取触发的事件的数组,在上面的代码中触发click时这个数组中是有两个值的,而触发mousedown时是只有一个值的,这个值是内部封装的一个handleObj对象
handlers = ((jQuery._data(this, "events") || {})[event.type] || [])

...

//之后会把这个handlers数组根据是否委托来slice(也是这个地方复制了handlers,导致click中的off第一次点击的时候无效),然后添加到数组handlerQueue中
handlerQueue.push({ elem: this, matches: handlers.slice(delegateCount) })

...
//最后触发的时候是遍历handlerQueue中的matches来执行
 for (i = 0; i < handlerQueue.length && !event.isPropagationStopped() ; i++) {
                matched = handlerQueue[i];
                event.currentTarget = matched.elem;

                for (j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped() ; j++) {
                    ...
                    }
}
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal