Can I remove event listeners with a Chrome extensi

2020-06-15 05:21发布

问题:

In Chrome's dev tools, there's a lovely interface where you can see all the event listeners attached to a given DOM element, and remove any of them as you see fit. Here's a screenshot (arrow added for emphasis):

I'd like to write a Chrome extension that automatically removes event listeners from any web page (I'm trying to write a Chrome extension to disable smooth scrolling on any website that tries to force it upon you -- I figure removing the 'wheel' listener from <body> is the most direct route to do this). Is there any JavaScript API available for accessing and modifying this list of event listeners from a Chrome extension, or is it limited to the dev tools GUI?

To be clear, I'm aware of removeEventListener(), but that method requires that you have a reference to the original listener object -- I have no such reference, so that method won't suit my purposes.

回答1:

eholder0's answer unfortunately doesn't help when the event listener is registered on window (like in your question) or document. For that, one way is that most code and libraries usually registers event listeners on the bubbling phase, by passing in false for the third useCapture parameter of addEventListener (or just not passing it in at all). Since the capturing phase happens first, you can prevent event listeners from being invoked by registering a capturing phase listener that stops further propagation.

For example, on a certain code review site (starts with "r" and ends with "eviewable.io") that removes the ability to use the middle mouse button click for scrolling via a mousedown event on document, the following in an extension's content script works:

document.addEventListener("mousedown", function (event) {
    event.stopPropagation();
}, true);

Notice the third parameter is true to register a capturing phase event listener. Also notice that it does not call event.preventDefault(), so the browser's inbuilt scrolling function is retained.



回答2:

Unfortunately because of how event listeners are implemented, this isn't trivially possible. There are some libraries you can use which record calls to add event listeners, thereby giving you a reference to remove. Short of using those or rolling your own, the isn't a simple tool to remove them anonymously.

You can however do something which will effectively remove all listeners, which is to clone the element and replace it with the clone. Cloning does not preserve any listeners on the element or its children, though it does otherwise preserve all attributes. Here's an example of how to do that:

var elem = document.getElementById('foo'),
clone = elem.cloneNode(true);
elem.parentNode.replaceChild(clone, elem);