Der Code lautet wie folgt:
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 );
Warum gibt dieser Code Handler1 und Handler2 aus, wenn er zum ersten Mal angeklickt wird? Das Aus in Handler1 funktioniert, aber Handler2 wird trotzdem einmal ausgeführt.
Siehe jQuery-Dokumentation
Die Erklärung im Dokument lautet: Das Hinzufügen oder Entfernen von Ereignishandlern für das aktuelle Element wird erst wirksam, wenn das Ereignis das nächste Mal behandelt wird.
Vielleicht ist mein Englisch zu schlecht, ich habe das Gefühl, dass der Ausdruck an dieser Stelle nicht sehr genau ist , es sollte sein Das Hinzufügen oder Löschen desselben Ereignisses ist während der aktuellen Verarbeitung ungültig. Ich habe beispielsweise die beiden Klicks wie folgt geändert
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 );
Dann wird nur Handler1 ausgegeben. Es ist ersichtlich, dass das Ausschalten von Mouseup in Mousedown erfolgreich ist
Zurück zum Anfang: Warum ist das Hinzufügen oder Löschen desselben Ereignisses während der aktuellen Verarbeitung ungültig? (Ich habe versucht, den Quellcode von jQuery zu finden, aber es war ziemlich kompliziert, also habe ich aufgegeben)
还是得从源码开始讲解
先看这里: https://github.com/jquery/jqu...
此处为事件分发的核心代码开始处,可见jquery分发事件时需调用 this.event.handler 求出事件回调的列表,此处 handlerQueue 只是内部事件列表一部分的拷贝,而你用 off 改变的是内部事件列表,对拷贝出的 handlerQueue 自然没有影响。
就像是全部的事件回调函数都存在锅里,当有事件发生时,jquery 会把一部回调拷贝,盛到碗里,然后依次执行碗里的函数。你 off 改变的仅是锅里的函数,碗里的不受影响。
可以把on可以看成把处理方法加到组件的一个事件处理数组里,off就是从数组里去掉这个方法。当事件触发时,jq就会一次执行事件处理数组里的方法,那么如果事件处理方法里调用了off会怎么样?文档里已经写的很清楚了,在当前事件触发循环里并不会立刻从数组里去掉该处理方法,只有当绑定的事件再触发时才会体现。
感谢大家
问题找到了,原因在于jq内部对于事件的封装处理时,同一类型的事件会添加到同一个数组中,而在触发事件时遍历又是这个数组的一个复制,off没有改变复制的数组,所以导致第一次click的时候输出了hanler2,而对于mousedown和mouseup,因为是不同类型的事件,是封装成两个数组的,所以在mousedown中off掉mouseup是有效的。也许表达的不是很好,贴几行主要的jq源码