Javascript/DOM: How to remove all events of a DOM

2019-01-02 17:36发布

Just question: Is there any way to completely remove all events of an object, e.g. a div?

EDIT: I'm adding per div.addEventListener('click',eventReturner(),false); an event.

function eventReturner() {
    return function() {
        dosomething();
    };
}

EDIT2: I found a way, which is working, but not possible to use for my case:

var returnedFunction;
function addit() {
    var div = document.getElementById('div');
    returnedFunction = eventReturner();
    div.addEventListener('click',returnedFunction,false); //You HAVE to take here a var and not the direct call to eventReturner(), because the function address must be the same, and it would change, if the function was called again.
}
function removeit() {
    var div = document.getElementById('div');
    div.removeEventListener('click',returnedFunction,false);
}

7条回答
与风俱净
2楼-- · 2019-01-02 18:14

I am not sure what you mean with remove all events. Remove all handlers for a specific type of event or all event handlers for one type?

Remove all event handlers

If you want to remove all event handlers (of any type), you could clone the element and replace it with its clone:

var clone = element.cloneNode(true);

Note: This will preserve attributes and children, but it will not preserve any changes to DOM properties.


Remove "anonymous" event handlers of specific type

The other way is to use removeEventListener() but I guess you already tried this and it didn't work. Here is the catch:

Calling addEventListener to an anonymous function creates a new listener each time. Calling removeEventListener to an anonymous function has no effect. An anonymous function creates a unique object each time is is called, it is not a reference to an existing object though it may call one. When adding an event listener in this manner be sure it is added only once, it is permanent (can not be removed) untill the object it was added to is destroyed.

You are essentially passing an anonymous function to addEventListener as eventReturner returns a function.

You have to possibilites to solve this:

  1. Don't use a function that returns a function. Use the function directly:

    function handler() {
        dosomething();
    }
    
    div.addEventListener('click',handler,false);
    
  2. Create a wrapper for addEventListener that stores a reference to the returned function and create some weird removeAllEvents function:

    var _eventHandlers = {}; // somewhere global
    
    function addListener(node, event, handler, capture) {
        if(!(node in _eventHandlers)) {
            // _eventHandlers stores references to nodes
            _eventHandlers[node] = {};
        }
        if(!(event in _eventHandlers[node])) {
            // each entry contains another entry for each event type
            _eventHandlers[node][event] = [];
        }
        // capture reference
        _eventHandlers[node][event].push([handler, capture]);
        node.addEventListener(event, handler, capture);
     }
    
    function removeAllListeners(node, event) {
        if(node in _eventHandlers) {
            var handlers = _eventHandlers[node];
            if(event in handlers) {
                var eventHandlers = handlers[event];
                for(var i = eventHandlers.length; i--;) {
                    var handler = eventHandlers[i];
                    node.removeEventListener(event, handler[0], handler[1]);
                }
            }
        }
    }
    

    And then you could use it with:

    addListener(div, 'click', eventReturner(), false)
    // and later
    removeListeners(div, 'click')
    

DEMO

Note: If your code runs for a long time and you are creating and removing a lot of elements, you would have to make sure to remove the elements contained in _eventHandlers when you destroy them.

查看更多
登录 后发表回答