code show as below:
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 );
Why does this code output handler1 and handler2 when it is clicked for the first time? Off in handler1 works but handler2 is still executed once. What is the reason?
Refer to jQuery documentation
The explanation in the document is: Adding or removing event handlers on the current element won't take effect until the next time the event is handled
Maybe my English is too bad, I feel that this place is not very accurate. , it should be The addition or deletion of the same event is invalid during the current processing. For example, I changed the two clicks to the following
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 );
Then only handler1 will be output. It can be seen that turning off mouseup in mousedown is successful
Back to the beginning, why is the addition or deletion of the same event invalid during the current processing? (I tried to find the source code of jQuery, but it was quite complicated, so I gave up)
You still have to start from the source code
Look here first: https://github.com/jquery/jqu...
This is the beginning of the core code for event distribution. It can be seen that jquery needs to call this.event.handler to find the list of event callbacks when distributing events. The handlerQueue here is just a copy of a part of the internal event list, and you use off to change it. It is an internal event list and has no effect on the copied handlerQueue.
It’s like all event callback functions are stored in the pot. When an event occurs, jquery will copy a callback, put it into the bowl, and then execute the functions in the bowl in sequence. What you change by off is only the function in the pot, and the function in the bowl is not affected.
You can think of on as adding a processing method to an event processing array of the component, and off as removing this method from the array. When an event is triggered, jq will execute the methods in the event processing array at once. So what will happen if off is called in the event processing method? The document has made it very clear that the processing method will not be removed from the array immediately in the current event triggering loop. It will only be reflected when the bound event is triggered again.
Thank you everyone
The problem has been found. The reason is that when jq internally encapsulates events, events of the same type will be added to the same array, and when the event is triggered, the traversal is a copy of this array, and off does not change the copy. Array, so Hanler2 is output when clicked for the first time. As for mousedown and mouseup, because they are different types of events, they are encapsulated into two arrays, so it is effective to turn off mouseup in mousedown. Maybe the expression is not very good, please post a few lines of main jq source code