我能用Chrome扩展程序删除事件监听器吗?

16
在Chrome的开发工具中,有一个漂亮的界面,可以看到所有附加到给定DOM元素的事件侦听器,并根据需要删除它们。这是一个屏幕截图(箭头用于强调):Removing an event listener with Chrome dev tools我想编写一个Chrome扩展程序,自动从任何网页中删除事件侦听器(我正在尝试编写一个Chrome扩展程序,以禁用任何试图强制进行平滑滚动的网站--我认为从<body>中删除“wheel”侦听器是最直接的方法)。是否有JavaScript API可用于从Chrome扩展访问和修改此事件侦听器列表,还是仅限于开发工具GUI?需要明确的是,我知道removeEventListener(),但该方法要求您有对原始侦听器对象的引用--我没有这样的引用,所以该方法不适合我的目的。
2个回答

22

不幸的是,eholder0的回答在事件监听器注册在window(就像你的问题)或document时没有帮助。针对此情况,一种方法是,大多数代码和库通常通过将第三个useCapture参数设置为false来注册冒泡阶段的事件监听器(或根本不传递它)。由于捕获阶段首先发生,您可以通过注册一个捕获阶段的监听器来阻止进一步的传播,从而防止事件监听器被调用。

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

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

...或更明确的表述:

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

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


根据评论的补充:如果您想要禁止处理程序的特定元素而不是document,则还可以在该元素上注册捕获处理程序,以便不影响文档中的其他事件。


哦我的神啊,这个完美地运作了!将其放入一个Greasemonkey脚本中(将事件类型从“mousedown”更改为“wheel”),它像魔法一样工作。现在它有点太过有效(例如,在GitHub文本编辑器中它会完全阻止滚动),但既然我知道了这个技巧,我可以对其进行微调。 - Hayden Schiff
抱歉,我不是有意要点踩,现在我无法更改它 :-( - Terrabits
此外,当网站使用外部文件作为事件监听器时,这种方法无法正常工作。我可以在文档中看到3个“副本”上的“visibilitychange”监听器,我的出现在底部。 - fjleon
此脚本可能会破坏鼠标滚轮事件的正常使用,例如在 Google 日历中从一个月导航到另一个月。 - kdb
1
我的天啊!找了这么久终于找到了,太棒了!你是上帝吗? - Radityo Ardi
显示剩余2条评论

3

很遗憾,由于事件监听器的实现方式,这并不是一件容易的事情。有一些库可以帮助您记录添加事件监听器的调用,从而为您提供删除的参考。除非使用这些库或自己编写代码,否则没有简单的工具可以匿名删除它们。

但是,您可以采取一些方法有效地删除所有监听器,即克隆元素并用克隆替换它。克隆不会保留元素或其子元素上的任何监听器,但它确实保留所有属性。以下是如何执行此操作的示例:

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

正如你所说,这会移除所有的监听器,而这通常不是人们所希望的。Arnavion的方法(被标记为答案)要好得多。 - danbae

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接