javascript 删除特定类型的所有事件侦听器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19469881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 15:41:37  来源:igfitidea点击:

Remove All Event Listeners of Specific Type

javascriptevents

提问by J S

I want to remove all event listeners of a specific type that were added using addEventListener(). All the resources I'm seeing are saying you need to do this:

我想删除使用addEventListener(). 我看到的所有资源都在说你需要这样做:

elem.addEventListener('mousedown',specific_function);
elem.removeEventListener('mousedown',specific_function);

But I want to be able to clear it without knowing what it is currently, like this:

但我希望能够在不知道它当前是什么的情况下清除它,如下所示:

elem.addEventListener('mousedown',specific_function);
elem.removeEventListener('mousedown');

回答by plalx

That is not possible without intercepting addEventListenercalls and keep track of the listeners or use a library that allows such features unfortunately. It would have been if the listeners collection was accessible but the feature wasn't implemented.

addEventListener不幸的是,如果不拦截调用并跟踪侦听器或使用允许此类功能的库,这是不可能的。如果可以访问 listeners 集合但未实现功能,则情况会如此

The closest thing you can do is to remove all listeners by cloning the element, which will not clone the listeners collection.

您可以做的最接近的事情是通过克隆元素来删除所有侦听器,这不会克隆侦听器集合。

Note: This will also remove listeners on element's children.

注意:这也将删除元素子元素上的侦听器。

var el = document.getElementById('el-id'),
    elClone = el.cloneNode(true);

el.parentNode.replaceChild(elClone, el);

回答by Chris Middleton

If your only goal by removing the listeners is to stop them from running, you can add an event listener to the window capturing and canceling all events of the given type:

如果您删除监听器的唯一目标是阻止它们运行,您可以向窗口添加一个事件监听器,捕获并取消给定类型的所有事件:

window.addEventListener(type, function (event) {
    event.stopPropagation();
}, true);

Passing in truefor the third parameter causes the event to be captured on the way down. Stopping propagation means that the event never reaches the listeners that are listening for it.

传入true第三个参数会导致事件在下降过程中被捕获。停止传播意味着事件永远不会到达正在侦听它的侦听器。

回答by Martin Wantke

You must override EventTarget.prototype.addEventListener to build an trap function for logging all 'add listener' calls. Something like this:

您必须覆盖 EventTarget.prototype.addEventListener 以构建用于记录所有“添加侦听器”调用的陷阱函数。像这样的东西:

var _listeners = [];

EventTarget.prototype.addEventListenerBase = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, listener)
{
    _listeners.push({target: this, type: type, listener: listener});
    this.addEventListenerBase(type, listener);
};

Then you can build an EventTarget.prototype.removeEventListeners:

然后你可以构建一个 EventTarget.prototype.removeEventListener s

EventTarget.prototype.removeEventListeners = function(targetType)
{
    for(var index = 0; index != _listeners.length; index++)
    {
        var item = _listeners[index];

        var target = item.target;
        var type = item.type;
        var listener = item.listener;

        if(target == this && type == targetType)
        {
            this.removeEventListener(type, listener);
        }
    }
}

In ES6 you can use a Symbol, to hide the original function and the list of all added listener directly in the instantiated object self.

在 ES6 中,您可以使用 Symbol,直接在实例化对象 self 中隐藏原始函数和所有添加的侦听器列表。

(function()
{
    let target = EventTarget.prototype;
    let functionName = 'addEventListener';
    let func = target[functionName];

    let symbolHidden = Symbol('hidden');

    function hidden(instance)
    {
        if(instance[symbolHidden] === undefined)
        {
            let area = {};
            instance[symbolHidden] = area;
            return area;
        }

        return instance[symbolHidden];
    }

    function listenersFrom(instance)
    {
        let area = hidden(instance);
        if(!area.listeners) { area.listeners = []; }
        return area.listeners;
    }

    target[functionName] = function(type, listener)
    {
        let listeners = listenersFrom(this);

        listeners.push({ type, listener });

        func.apply(this, [type, listener]);
    };

    target['removeEventListeners'] = function(targetType)
    {
        let self = this;

        let listeners = listenersFrom(this);
        let removed = [];

        listeners.forEach(item =>
        {
            let type = item.type;
            let listener = item.listener;

            if(type == targetType)
            {
                self.removeEventListener(type, listener);
            }
        });
    };
})();

You can test this code with this little snipper:

你可以用这个小狙击手测试这段代码:

document.addEventListener("DOMContentLoaded", event => { console.log('event 1'); });
document.addEventListener("DOMContentLoaded", event => { console.log('event 2'); });
document.addEventListener("click", event => { console.log('click event'); });

document.dispatchEvent(new Event('DOMContentLoaded'));
document.removeEventListeners('DOMContentLoaded');
document.dispatchEvent(new Event('DOMContentLoaded'));
// click event still works, just do a click in the browser

回答by PaladinMattt

I know this is old, but I had a similar issue with no real answers, where I wanted to remove all "keydown" event listeners from the document. Instead of removing them, I overrode the addEventListener to ignore them before they were even added, similar to Toms answer above, by adding this before any other scripts are loaded.:

我知道这是旧的,但我有一个没有真正答案的类似问题,我想从文档中删除所有“keydown”事件侦听器。我没有删除它们,而是在添加它们之前覆盖 addEventListener 以忽略它们,类似于上面的 Toms 回答,通过在加载任何其他脚本之前添加它。:

<script type="text/javascript">
    var current = document.addEventListener;
    document.addEventListener = function (type, listener) {
        if(type =="keydown")
        {
            //do nothing
        }
        else
        {
            var args = [];
            args[0] = type;
            args[1] = listener;
            current.apply(this, args);
        }
    };
</script>

回答by yves amsellem

In the extreme case of not knowing which callback is attached to a window listener, an handler can be wrapper around window addEventListenerand a variable can store ever listeners to properly remove each one of those through a removeAllEventListener('scroll')for example.

在不知道哪个回调附加到窗口侦听器的极端情况下,处理程序可以围绕窗口进行包装,addEventListener并且变量可以存储所有侦听器以通过removeAllEventListener('scroll')例如正确删除每个侦听器。

var listeners = {};

var originalEventListener = window.addEventListener;
window.addEventListener = function(type, fn, options) {
    if (!listeners[type])
        listeners[type] = [];

    listeners[type].push(fn);
    return originalEventListener(type, fn, options);
}

var removeAllEventListener = function(type) {
    if (!listeners[type] || !listeners[type].length)
        return;

    for (let i = 0; i < listeners[type].length; i++)
        window.removeEventListener(type, listeners[type][i]);
}

回答by Mike Sraj

So this function gets rid of most of a specified listener type on an element:

所以这个函数摆脱了元素上大部分指定的侦听器类型:

function removeListenersFromElement(element, listenerType){
  const listeners = getEventListeners(element)[listenerType];
  let l = listeners.length;
  for(let i = l-1; i >=0; i--){
    removeEventListener(listenerType, listeners[i].listener);
  }
 }

There have been a few rare exceptions where one can't be removed for some reason.

有一些罕见的例外,由于某种原因无法删除。

回答by Tom Burris

You could alternatively overwrite the 'yourElement.addEventListener()' method and use the '.apply()' method to execute the listener like normal, but intercepting the function in the process. Like:

您也可以覆盖 'yourElement.addEventListener()' 方法并使用 '.apply()' 方法像往常一样执行侦听器,但在进程中拦截函数。喜欢:

<script type="text/javascript">

    var args = [];
    var orginalAddEvent = yourElement.addEventListener;

    yourElement.addEventListener = function() {
        //console.log(arguments);
        args[args.length] = arguments[0];
        args[args.length] = arguments[1];
        orginalAddEvent.apply(this, arguments);
    };

    function removeListeners() {
        for(var n=0;n<args.length;n+=2) {
            yourElement.removeEventListener(args[n], args[n+1]);
        }
    }

    removeListeners();

</script>

This script must be run on page load or it might not intercept all event listeners.

此脚本必须在页面加载时运行,否则它可能不会拦截所有事件侦听器。

Make sure to remove the 'removeListeners()' call before using.

确保在使用前删除 'removeListeners()' 调用。

回答by Nazar Vynnytskyi

Remove all listeners in element by one js line:

通过一行 js 行删除 element 中的所有侦听器:

element.parentNode.innerHTML += '';

回答by Sri Harsha

 var events = [event_1, event_2,event_3]  // your events

//make a for loop of your events and remove them all in a single instance

 for (let i in events){
    canvas_1.removeEventListener("mousedown", events[i], false)
}

回答by McKabue

You cant remove a single event, but all? at once? just do

您不能删除单个事件,但所有事件?立刻?做就是了

document.body.innerHTML = document.body.innerHTML

document.body.innerHTML = document.body.innerHTML