【问题标题】:Event bubbling & propagation hierarchy事件冒泡和传播层次结构
【发布时间】:2017-08-16 20:55:15
【问题描述】:

我目前正在开发一个 chrome 扩展程序,我需要防止在加载该扩展程序的任何页面上发生默认点击操作。通常我会做类似下面的事情来防止默认操作:

$('.some-element').click(function(e){
 e.preventDefault()

// some other code

});

我在这里使用与我的扩展相同的方法,但我发现有时这会奏效,而其他时候则不会。例如,如果我访问一个站点,其中页面区域中的 <a> 标记已经绑定了 preventDefault,那么该网站的 preventDefault 将阻止我的事件运行..

点击事件的层次结构是如何工作的 - 是不是加载的第一个函数总是首先触发?如果是这样,有没有办法可以对事件施加层次结构,以便我的事件总是首先触发,从而防止页面上加载任何其他操作?

页面上已经存在的操作只需要暂时禁用,因此如果我不能再次绑定它们,我完全取消绑定所有事件的方法可能不适合..

谢谢

【问题讨论】:

  • 你是说你在注入 JavaScript 代码来监听点击事件,我假设在 Chrome 的开发者控制台中为其他人的网站?我很困惑你如何提到你的网站和其他网站。如果您尝试做我认为您正在尝试做的事情,我认为它不会奏效。
  • 基本上,我试图通过我通过内容脚本注入页面的代码来阻止任何默认的 onClick 事件在网站上触发。从那里我想用我自己的函数做几件事。到目前为止,它有效,但就像我说的那样,如果网站上的元素上已经设置了 event.preventDefault,那么与我通过内容脚本注入页面的 event.preventDefault 相反,那个 event.peventDefault 将触发。我不认为我曾经提到过我的网站......这是一个 chrome 扩展
  • 在最顶层的 DOM 对象 window 上附加一个 mousedown 侦听器,并为 addEventListener 的 useCapture 参数指定 true 以在从窗口到单击目标的捕获阶段一开始就拦截事件。此代码将在目标的 mousedown 之前运行。如果您在 document_start 上运行的内容脚本中执行此操作,则任何页面都无法取代它。
  • 这完全有道理,明天早上会尝试,让你知道它是否有效。谢谢!

标签: javascript jquery google-chrome-extension


【解决方案1】:

请注意,普通事件监听器 (Element.addEventListener) 和 jQuery .click/.on 是两个不同的东西。 jQuery 设置一次监听器,并有其内部的回调数组。

如果您想阻止所有特定类型的侦听器触发,请使用捕获模式(第三个参数)将侦听器添加到窗口:

window.addEventListener('mousedown', (e) => {
  e.preventDefault()
}, true);

【讨论】:

  • 好的,你会说结合 wOxxOm 的建议:使用 mousedown 事件侦听器而不是 click 并将事件侦听器添加到 window 而不是 body 会为上面的代码增加更多确定性吗?
  • @BenLiger 是的,当然。完成。
  • 差不多了...在修改我的代码后,我的事件现在会在以前没有的网站上触发。现在唯一的问题是我的默认阻止似乎不起作用,即页面上的其他功能仍在与我的并行触发..
  • @BenLiger,那是因为你混淆了Event.preventDefault()Event.stopPropagation()Event.stopImmediatePropagation() 的效果。另请注意,如果您想确保事件处理程序在页内处理程序之前运行,您的脚本需要运行 document_start