【问题标题】:Can't remove all event listeners无法删除所有事件侦听器
【发布时间】:2018-06-29 22:10:00
【问题描述】:

我正在尝试从某个网站上删除事件侦听器,但我没有成功。

这是来自网站的事件监听器:

有一个 javascript 脚本可以创建这些事件:

document.addEventListener('contextmenu', function (ev) {
        ev.preventDefault();
    }
)

我试图删除它:

document.removeEventListener('contextmenu', function (ev) {
                ev.preventDefault();
            }) 

我也试过:

(getEventListeners(document)).contextmenu = null

但它不起作用,我想是因为我使用了一个不同的新功能。

有没有办法清除所有事件?

参考:
Can't remove event listener

【问题讨论】:

    标签: javascript event-listener


    【解决方案1】:

    你需要指定绑定到removeEventListener的函数

    您可以通过创建一个函数并传递对addEventListenerremoveEventListener 的引用来做到这一点。

    // create a function
    function onRightClick(ev) {
      ev.preventDefault();
      console.log('onRightClick')
    }
    
    // pass the function to both add and remove
    document.addEventListener('contextmenu', onRightClick)
    document.removeEventListener('contextmenu', onRightClick)

    这是一个完整的示例,它将缓存所有事件到元素,允许您删除特定事件,所有事件的类型为所有事件。

    它还有一个 MutationObserver 监视 DOM 的变化,如果一个元素被删除,附加到它的事件也会被删除。

    const Events = (() => {
      
      const cache = new Map
      
      const observer = new MutationObserver(function(mutations) {
        for (let mutation of mutations) {
          if (mutation.type === 'childList') {
            if (mutation.removedNodes.length) {
              console.log('element removed from the dom, removing all events for the element')
              mutation.removedNodes.forEach(x => Events.remove(x))
            }
          }
        }
      })
      
      // watch the dom for the element being deleted
      observer.observe(document.body, { childList: true })
      
      return {
      
        add(el, type, fn, capture = false) {
          let cached = cache.get(el)
          if (!cached) {
            cached = {}
            cache.set(el, cached)
          }
          if (!cached[type]) {
            cached[type] = new Set
          }
          cached[type].add(fn)
          el.addEventListener(type, fn, capture)
        },
        
        remove(el, type, fn) {
          const cached = cache.get(el)
          if (!cached) {
            return false
          }
          // remove all events for an event type
          if (type && !fn) {
            cached[type].forEach(fn => {
              el.removeEventListener(type, fn)
            })
            cached[type] = new Set
          }
          // remove a specific event
          else if (type && fn) {
            el.removeEventListener(type, fn)
            // remove the event from the cache
            cached[type].delete(fn)
          }
          // remove all events for the element
          else {
            for (key in cached) {
              cached[key].forEach(fn => {
                el.removeEventListener(key, fn)
              })
            }
            cache.delete(el)
          }
        },
        
        show(el, type) {
          const cached = cache.get(el)
          if (!cached) {
            return false
          }
          if (type) {
            return cached[type]
          }
          return cached
        }
      }
    })()
    
    function onRightClick() {}
    
    Events.add(document, 'contextmenu', onRightClick)
    Events.remove(document, 'contextmenu', onRightClick) // remove a specific event callback
    Events.remove(document, 'contextmenu') // remove specific event types from an element
    Events.remove(document) // remove all events from an element
    
    
    const testElement = document.querySelector('#test_element')
    
    Events.add(testElement, 'click', function deleteSelf(e) {
      this.parentNode.removeChild(this)
    })
    <div id="test_element">
      when you <strong>click me</strong> I will be deleted from the DOM which will fire the MutationObserver to remove all my events
    </div>

    【讨论】:

    • 好的,我认为有一些东西可以在不需要函数引用的情况下清除所有事件。
    • 否,但您可以创建自己的实用程序函数来绑定事件,然后全部删除。
    【解决方案2】:

    您可以尝试克隆已添加所有侦听器的元素并将其添加回其父级。使用cloning,您将失去所有附加到该元素的侦听器。试试这个,

    var element = document.getElementById('myElement'),
        clone = el.cloneNode(true);
    
    element.parentNode.replaceChild(clone, element);
    

    但是,这不适用于全局事件侦听器,或者简单地说,那些直接设置在文档而不是元素上的事件侦听器,因为文档是层次结构的根(不能有 parentNode)

    【讨论】:

      【解决方案3】:

      要摆脱未知的事件侦听器,您可以clone 元素,然后将原始内容移动到克隆的内容中,然后用克隆替换原始内容。

      如果你不关心包含的元素的事件监听器,你也可以用.clone(true)(或者false,不记得了)深度克隆原件。这样你就不必把内容移过来了。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-04
      • 1970-01-01
      • 1970-01-01
      • 2018-09-04
      • 2018-07-15
      • 2020-11-13
      • 2022-08-03
      • 2013-10-28
      相关资源
      最近更新 更多