Javascript/DOM:如何删除DOM对象的所有事件?

Javascript/DOM:如何删除DOM对象的所有事件?,javascript,events,dom,Javascript,Events,Dom,问:有没有办法完全删除对象的所有事件,例如div 编辑:我正在添加perdiv.addEventListener('click',eventReturner(),false)事件 function eventReturner() { return function() { dosomething(); }; } EDIT2:我找到了一种可行的方法,但不可能用于我的案例: var returnedFunction; function addit() { v

问:有没有办法完全删除对象的所有事件,例如div

编辑:我正在添加per
div.addEventListener('click',eventReturner(),false)事件

function eventReturner() {
    return function() {
        dosomething();
    };
}
EDIT2:我找到了一种可行的方法,但不可能用于我的案例:

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);
}
//编辑

我不知道你用什么方法附加事件。对于
addEventListener
,您可以使用:

div.removeEventListener('click',functionName,false); // functionName is the name of your callback function

如果您执行以下操作,浏览器可能会为您执行此操作:


复制
div
及其属性,并将其插入到旧的属性之前,然后将内容从旧内容移动到新内容并删除旧内容?

我不确定您对删除所有事件的意思。删除特定类型事件的所有处理程序,还是删除一种类型的所有事件处理程序

删除所有事件处理程序 如果要删除所有事件处理程序(任何类型),可以删除元素并用其克隆替换它:

var clone = element.cloneNode(true);
注意:这将保留属性和子级,但不会保留对DOM属性的任何更改


删除特定类型的“匿名”事件处理程序 另一种方法是使用,但我想你已经尝试过了,但没有效果

对匿名函数调用
addEventListener
,每次都会创建一个新的侦听器。对匿名函数调用
removeEventListener
无效。匿名函数每次调用时都会创建一个唯一的对象,它不是对现有对象的引用,尽管它可能会调用一个对象。以这种方式添加事件侦听器时,请确保只添加一次,它是永久的(无法删除),直到它添加到的对象被销毁

实际上,您是在向
addEventListener
传递一个匿名函数,因为
eventReturner
返回一个函数

您有两种可能解决此问题:

  • 不要使用返回函数的函数。直接使用该功能:

     function handler() {
         dosomething();
     }
    
     div.addEventListener('click',handler,false);
    
  • addEventListener
    创建一个包装器,该包装器存储对返回函数的引用,并创建一些奇怪的
    removeAllEvents
    函数:

     var _eventHandlers = {}; // somewhere global
    
     const addListener = (node, event, handler, capture = false) => {
       if (!(event in _eventHandlers)) {
         _eventHandlers[event] = []
       }
       // here we track the events and their nodes (note that we cannot
       // use node as Object keys, as they'd get coerced into a string
       _eventHandlers[event].push({ node: node, handler: handler, capture: capture })
       node.addEventListener(event, handler, capture)
     }
    
     const removeAllListeners = (targetNode, event) => {
       // remove listeners from the matching nodes
       _eventHandlers[event]
         .filter(({ node }) => node === targetNode)
         .forEach(({ node, handler, capture }) => node.removeEventListener(event, handler, capture))
    
       // update _eventHandlers global
       _eventHandlers[event] = _eventHandlers[event].filter(
         ({ node }) => node !== targetNode,
       )
     }
    
  • 然后您可以将其用于:

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


    注意:如果您的代码运行很长时间,并且您正在创建和删除许多元素,那么在销毁它们时,您必须确保删除
    \u eventHandlers
    中包含的元素。

    这将从子级删除所有侦听器,但对于大型页面来说速度较慢。写起来极其简单

    element.outerHTML = element.outerHTML;
    

    使用事件侦听器自己的函数
    remove()
    。例如:

    getEventListeners().click.forEach((e)=>{e.remove()})
    

    正如corwin.amber所说,Webkit和其他工具之间存在差异

    铬合金:

    getEventListeners(document);
    
    这将为您提供一个包含所有现有事件侦听器的对象:

    Object 
     click: Array[1]
     closePopups: Array[1]
     keyup: Array[1]
     mouseout: Array[1]
     mouseover: Array[1]
     ...
    
    从这里,您可以访问要删除的侦听器:

    getEventListeners(document).copy[0].remove();
    
    document.removeEventListener("copy", getEventListeners(document).copy[0].listener)
    
    因此,所有事件侦听器:

    Object 
     click: Array[1]
     closePopups: Array[1]
     keyup: Array[1]
     mouseout: Array[1]
     mouseover: Array[1]
     ...
    
    for(getEventListeners(文档)中的var eventType){
    getEventListeners(文档)[eventType].forEach(
    函数(o){o.remove();}
    ) 
    }
    
    Firefox中的

    有点不同,因为它使用了不包含删除函数的侦听器包装器。您必须获取要删除的侦听器:

    getEventListeners(document).copy[0].remove();
    
    document.removeEventListener("copy", getEventListeners(document).copy[0].listener)
    
    所有事件侦听器:

    我无意中发现了这篇试图禁用新闻网站恼人的版权保护的帖子


    享受吧

    删除
    文档上的所有事件

    一艘班轮:

    for (key in getEventListeners(document)) { getEventListeners(document)[key].forEach(function(c) { c.remove() }) }
    
    漂亮版:

    for (key in getEventListeners(document)) {
      getEventListeners(document)[key].forEach(function(c) {
        c.remove()
      })   
    }
    

    仅限铬合金

    因为我试图删除量角器测试中的EventListener,并且无法访问 在测试中,以下操作可删除单一类型的所有事件侦听器:

    function(eventType){
        getEventListeners(window).[eventType].forEach(
            function(e){
                window.removeEventListener(eventType, e.listener)
            }
        );
    }
    

    我希望这对其他人有所帮助,因为之前的答案使用的是“删除”方法,从那以后就不再有效了。

    为了完成这些答案,这里有一些真实的示例,说明在访问网站时删除事件,并且无法控制生成的HTML和JavaScript代码

    一些恼人的网站阻止您在登录表单上复制粘贴用户名,如果在
    onpaste
    事件中添加了
    onpaste=“return false”
    HTML属性,则很容易绕过此操作。 在本例中,我们只需右键单击输入字段,在类似Firefox的浏览器中选择“Inspect element”,然后删除HTML属性

    但是,如果事件是通过JavaScript添加的,如下所示:

    document.getElementById("lyca_login_mobile_no").onpaste = function(){return false};
    
    我们还必须通过JavaScript删除该事件:

    document.getElementById("lyca_login_mobile_no").onpaste = null;
    
    在我的示例中,我使用ID“lyca_login_mobile_no”,因为它是我访问的网站使用的文本输入ID

    删除事件的另一种方法(也将删除所有事件)是删除节点并创建一个新的节点,就像使用
    addEventListener
    添加事件时使用的匿名函数一样,我们不能使用
    removeEventListener
    删除该函数。 也可以通过浏览器控制台检查元素、复制HTML代码、删除HTML代码,然后在同一位置粘贴HTML代码来完成此操作

    还可以通过JavaScript更快地实现自动化:

    var oldNode = document.getElementById("lyca_login_mobile_no");
    var newNode = oldNode.cloneNode(true);
    oldNode.parentNode.insertBefore(newNode, oldNode);
    oldNode.parentNode.removeChild(oldNode);
    
    document.getElementById("lyca_login_mobile_no").value = "username";
    
    更新:如果web应用程序是使用类似Angular的JavaScript框架制作的,那么之前的解决方案似乎不起作用或破坏了应用程序。 允许粘贴的另一个解决方法是通过JavaScript设置值:

    var oldNode = document.getElementById("lyca_login_mobile_no");
    var newNode = oldNode.cloneNode(true);
    oldNode.parentNode.insertBefore(newNode, oldNode);
    oldNode.parentNode.removeChild(oldNode);
    
    document.getElementById("lyca_login_mobile_no").value = "username";
    

    目前,我不知道是否有一种方法可以在不破坏像Angular这样完全用JavaScript编写的应用程序的情况下删除所有表单验证和限制事件。

    一种方法是添加一个新的事件侦听器,调用e.stopImmediatePropagation()。

    Angular对此问题有一个polyfill,您可以检查。我不太明白,但也许这能帮上忙

    const REMOVE_ALL_LISTENERS_EVENT_LISTENER='removeAllListeners'

        proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function () {
            const target = this || _global;
            const eventName = arguments[0];
            if (!eventName) {
                const keys = Object.keys(target);
                for (let i = 0; i < keys.length; i++) {
                    const prop = keys[i];
                    const match = EVENT_NAME_SYMBOL_REGX.exec(prop);
                    let evtName = match && match[1];
                    // in nodejs EventEmitter, removeListener event is
                    // used for monitoring the removeListener call,
                    // so just keep removeListener eventListener until
                    // all other eventListeners are removed
                    if (evtName && evtName !== 'removeListener') {
                        this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, evtName);
                    }
                }
                // remove removeListener listener finally
                this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener');
            }
            else {
                const symbolEventNames = zoneSymbolEventNames$1[eventName];
                if (symbolEventNames) {
                    const symbolEventName = symbolEventNames[FALSE_STR];
                    const symbolCaptureEventName = symbolEventNames[TRUE_STR];
                    const tasks = target[symbolEventName];
                    const captureTasks = target[symbolCaptureEventName];
                    if (tasks) {
                        const removeTasks = tasks.slice();
                        for (let i = 0; i < removeTasks.length; i++) {
                            const task = removeTasks[i];
                            let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
                            this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);
                        }
                    }
                    if (captureTasks) {
                        const removeTasks = captureTasks.slice();
                        for (let i = 0; i < removeTasks.length; i++) {
                            const task = removeTasks[i];
                            let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
                            this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);
                        }
                    }
                }
            }
            if (returnTarget) {
                return this;
            }
        };
    
    proto[删除所有列表]
    
    <div id="test" onclick="alert(42)">test</div>
    
    const removeAttEvents = el =>
        [...el.attributes].forEach(att =>
            att.name.startsWith("on") && el.removeAttribute(att.name)
        );