removeEventListener而不知道函数

removeEventListener without knowing the function

本文关键字:函数 不知道 removeEventListener      更新时间:2023-09-26

一些第三方插件会将eventListener附加到站点中。如何在不知道附加的函数的情况下删除eventListener。

我引用了这个removeEventListener,但我找不到任何删除它的线索。

例如:getEventListeners(window)显示附加的事件。但是,当我尝试使用window.removeEventListener("eventname")删除事件时,在不知道该函数的情况下无法工作。

请帮忙,提前谢谢。

getEventListeners(window)将返回事件及其注册的事件侦听器的映射。

因此,例如,对于DOMContentLoaded事件,可以有许多事件侦听器。如果你知道要删除的侦听器的索引(或者如果只有一个),你可以这样做:

var eventlistener = getEventListeners(window)["DOMContentLoaded"][index];
window.removeEventListener("DOMContentLoaded", 
                           eventlistener.listener,
                           eventlistener.useCapture);

很遗憾,您无法做到这一点。需要引用事件处理程序函数,以便通过removeEventListener删除它。

如果您无法获得该引用,您唯一的选择是完全替换Node

注意事项:使用Chrome和Edge中提供的特定于浏览器的getEventListeners

如果需要删除所有事件侦听器:

// selector is optional - defaults to all elements including window and document
// Do not pass window / document objects. Instead use pseudoselectors: 'window' or 'document'
// eTypeArray is optional - defaults to clearing all event types
function removeAllEventListeners(selector = '*', eTypeArray = ['*']) {
  switch (selector.toLowerCase()) {
    case 'window':
      removeListenersFromElem(window);
      break;
    case 'document':
      removeListenersFromElem(document);
      break;
    case '*':
      removeListenersFromElem(window);
      removeListenersFromElem(document);
    default:
      document.querySelectorAll(selector).forEach(removeListenersFromElem);
  }
  
  function removeListenersFromElem(elem) {
    let eListeners = getEventListeners(elem);
    let eTypes = Object.keys(eListeners);
    for (let eType of inBoth(eTypes, eTypeArray)) {
      eListeners[eType].forEach((eListener)=>{
        let options = {};
        inBoth(Object.keys(eListener), ['capture', 'once', 'passive', 'signal'])
          .forEach((key)=>{ options[key] = eListener[key] });
        elem.removeEventListener(eType, eListener.listener, eListener.useCapture);
        elem.removeEventListener(eType, eListener.listener, options);
      });
    }
  }
  function inBoth(arrA, arrB) {
    setB = new Set(arrB);
    if (setB.has('*')) {
      return arrA;
    } else {
      return arrA.filter(a => setB.has(a));
    }
  }
}

用途:

removeAllEventListeners('a.fancyLink'); // remove all event types
removeAllEventListeners('a.fancyLink', ['click', 'hover']); // remove these types
removeAllEventListeners('*', ['click', 'hover']); // remove these types everywhere
removeAllEventListeners(); // remove everything you can

注意,这可能并不总是有效的。每个MDN:

值得注意的是,一些浏览器版本在这方面存在不一致性,除非您有其他特定原因,否则在调用removeEventListener()时,使用与调用addEventListener()相同的值可能是明智的。

我使用options试图通过希望使用添加侦听器时使用的相同值来调用removeEventListener来处理这个问题。

更新:2023

EventListeners可以在不知道实际函数引用的情况下删除。但它只能在现代浏览器中使用。

使用AbortController删除事件。使用AbortSignal,您可以简单地获得信号来为您删除它:

样本代码:

const controller = new AbortController();
const { signal } = controller;
window.addEventListener('resize', () => doSomething(), { signal });
controller.abort(); // It wll remove the "resize" event handler.

您可以检查并为旧浏览器添加polyfill

相关文章: