JavaScript:删除事件侦听器

我正在尝试删除侦听器定义中的事件侦听器:

canvas.addEventListener('click', function(event) {
click++;
if(click == 50) {
// remove this event listener here!
}
// More code here ...

我怎么能这么做?此=事件..

325208 次浏览

If @Cybernate's solution doesn't work, try breaking the trigger off in to it's own function so you can reference it.

clickHandler = function(event){
if (click++ == 49)
canvas.removeEventListener('click',clickHandler);
}
canvas.addEventListener('click',clickHandler);

You need to use named functions.

Also, the click variable needs to be outside the handler to increment.

var click_count = 0;


function myClick(event) {
click_count++;
if(click_count == 50) {
// to remove
canvas.removeEventListener('click', myClick);
}
}


// to add
canvas.addEventListener('click', myClick);

EDIT: You could close around the click_counter variable like this:

var myClick = (function( click_count ) {
var handler = function(event) {
click_count++;
if(click_count == 50) {
// to remove
canvas.removeEventListener('click', handler);
}
};
return handler;
})( 0 );


// to add
canvas.addEventListener('click', myClick);

This way you can increment the counter across several elements.


If you don't want that, and want each one to have its own counter, then do this:

var myClick = function( click_count ) {
var handler = function(event) {
click_count++;
if(click_count == 50) {
// to remove
canvas.removeEventListener('click', handler);
}
};
return handler;
};


// to add
canvas.addEventListener('click', myClick( 0 ));

EDIT: I had forgotten to name the handler being returned in the last two versions. Fixed.

I think you may need to define the handler function ahead of time, like so:

var myHandler = function(event) {
click++;
if(click == 50) {
this.removeEventListener('click', myHandler);
}
}
canvas.addEventListener('click', myHandler);

This will allow you to remove the handler by name from within itself.

   canvas.addEventListener('click', function(event) {
click++;
if(click == 50) {
this.removeEventListener('click',arguments.callee,false);
}

Should do it.

element.querySelector('.addDoor').onEvent('click', function (e) { });
element.querySelector('.addDoor').removeListeners();




HTMLElement.prototype.onEvent = function (eventType, callBack, useCapture) {
this.addEventListener(eventType, callBack, useCapture);
if (!this.myListeners) {
this.myListeners = [];
};
this.myListeners.push({ eType: eventType, callBack: callBack });
return this;
};




HTMLElement.prototype.removeListeners = function () {
if (this.myListeners) {
for (var i = 0; i < this.myListeners.length; i++) {
this.removeEventListener(this.myListeners[i].eType, this.myListeners[i].callBack);
};
delete this.myListeners;
};
};

You could use a named function expression (in this case the function is named abc), like so:

let click = 0;
canvas.addEventListener('click', function abc(event) {
click++;
if (click >= 50) {
// remove event listener function `abc`
canvas.removeEventListener('click', abc);
}
// More code here ...
}

Quick and dirty working example: http://jsfiddle.net/8qvdmLz5/2/.

More information about named function expressions: http://kangax.github.io/nfe/.

If someone uses jquery, he can do it like this :

var click_count = 0;
$( "canvas" ).bind( "click", function( event ) {
//do whatever you want
click_count++;
if ( click_count == 50 ) {
//remove the event
$( this ).unbind( event );
}
});

Hope that it can help someone. Note that the answer given by @user113716 work nicely :)

Try this, it worked for me.

<button id="btn">Click</button>
<script>
console.log(btn)
let f;
btn.addEventListener('click', f=function(event) {
console.log('Click')
console.log(f)
this.removeEventListener('click',f)
console.log('Event removed')
})
</script>

It looks like no one's covered the part of the current JavaScript DOM specification that gives you a mechanism to remove your event listener without using removeEventListener. If we look at https://dom.spec.whatwg.org/#concept-event-listener we see that there are a number of properties that can be passed to control event listening:

{
type (a string)
callback (null or an EventListener object)
capture (a boolean, initially false)
passive (a boolean, initially false)
once (a boolean, initially false)
signal (null or an AbortSignal object)
removed (a boolean for bookkeeping purposes, initially false)
}

Now, there's a lot of useful properties in that list, but for the purposes of removing an event listener it's the signal property that we want to make use of (which was added to the DOM level 3 in late 2020), because it lets us tell the JS engine to remove an event listener by just calling abort() instead of having to bother with removeEventListener:

const canvasListener = (new AbortController()).signal;


canvas.addEventListener('click', () => {
click++;
if (click === 50) {
canvasListener.abort();
} else {
doSomethingWith(click);
}
}, {
signal: canvasListener
});

(Note that this does not use the useCapture flag, because the useCapture flag is essentially completely useless)

And done: the JS engine will abort and clean up our event listener. No keeping a reference to the handling function, no making sure we call removeEventListener with the exact same properties as we called addEventListener: we just cancel the listener.

A way to achieve that is use jquery, so you can use:

canvas.click(yourfunction);

then you can detach all event listener with:

canvas.off();