我可以删除带有 Chrome 扩展名的事件侦听器吗?

Can I remove event listeners with a Chrome extension?

在 Chrome 的开发工具中,有一个可爱的界面,您可以在其中查看附加到给定 DOM 元素的所有事件侦听器,并根据需要删除其中的任何一个。这是屏幕截图(为强调而添加的箭头):

Removing an event listener with Chrome dev tools

我想编写一个 Chrome 扩展程序,自动从任何网页中删除事件侦听器(我正在尝试编写一个 Chrome 扩展程序以禁用任何尝试的网站上的平滑滚动强加给你——我认为从 <body> 中删除 'wheel' 侦听器是最直接的方法)。是否有任何 JavaScript API 可用于从 Chrome 扩展访问和修改此事件侦听器列表,或者它是否仅限于开发工具 GUI?

明确地说,我知道 removeEventListener(),但该方法要求您有对原始侦听器对象的引用——我没有这样的引用,因此该方法不适合我目的。

不幸的是,由于事件侦听器的实现方式,这并非易事。您可以使用一些库来记录调用以添加事件侦听器,从而为您提供删除参考。除了使用它们或自己滚动之外,这不是一个匿名删除它们的简单工具。

但是,您可以执行一些操作来有效地删除所有侦听器,即克隆元素并将其替换为克隆元素。克隆不会保留元素或其子元素上的任何侦听器,但它会保留所有属性。这是一个如何做到这一点的例子:

var elem = document.getElementById('foo'),
clone = elem.cloneNode(true);
elem.parentNode.replaceChild(clone, elem);    
不幸的是,当事件侦听器在 window(如您的问题)或 document 上注册时,

eholder0 的回答没有帮助。为此,一种方法是大多数代码和库通常在冒泡阶段注册事件侦听器,方法是为 addEventListener 的第三个 useCapture 参数传递 false(或者根本不传递它)。由于捕获阶段首先发生,您可以通过注册停止进一步传播的捕获阶段侦听器来防止调用事件侦听器。

因此,对于您的情况,您可以在扩展程序的内容脚本中执行以下操作:

document.addEventListener("wheel", event => event.stopPropagation(), true);

...或更明确地说:

document.addEventListener("wheel", event => event.stopPropagation(), { capture: true });

注意第三个参数是true,用于注册捕获阶段事件侦听器。另请注意,它调用event.preventDefault(),因此保留了浏览器的内置滚动功能。


基于评论的附录:如果您要抑制的处理程序位于特定元素而不是 document,您还可以在该元素上注册捕获处理程序,以便事件在文档的其余部分不受影响。