【问题标题】:Internet Explorer leaks click event after adding an overlay in a jQuery mousedown handler在 jQuery mousedown 处理程序中添加覆盖后 Internet Explorer 泄漏单击事件
【发布时间】:2013-10-13 11:18:06
【问题描述】:

在 div 的 mousedown 事件处理程序中,会创建另一个新 div 并将其附加到主体。
这个新的 div 有 position:fixed(也可以是 position:absolute),并且有 100% 的宽度和 100% 的高度。因此它会立即覆盖触发鼠标按下事件的源 div。 现在使用最新的 Google Chrome (v30)、最新的 Firefox (v24)、Opera v12.16,甚至使用较旧的 Safari v5.1.1(在 Windows 上)在 mousedown 事件 no 点击事件被触发后附加到主体的事件侦听器。
Internet Explorer(9 和 10) 触发主体上的点击事件!为什么?如何防止这种情况发生?这实际上是 IE 中的错误吗?

HTML:

<div class="clickme">Click me</div>

CSS:

.clickme {
    background-color: #BBB;
}

.overlay {
    position: fixed; /* or absolute */
    left: 0;
    top: 0;
    height: 100%;
    width: 100%;
    background-color: #000;
}

JavaScript:

$(document).on('click', function(event) {
    console.log('body click');
});

$('.clickme').on('mousedown', function(event) {
    console.log('div mousedown');
    
    var mask = $('<div></div>');
    mask.attr('class', 'overlay');
    mask.appendTo('body');
});

这是一个带有一些额外 cmets 的示例:http://jsfiddle.net/Fh4sK/5/

点击“点击我”div后,只有

div mousedown

应该写入控制台,但在 Internet Explorer 中它实际上是

div mousedown
body click

感谢您的帮助!谢谢!

编辑 1:

我找到了一些描述何时触发点击事件的条件的资源:

http://www.quirksmode.org/dom/events/click.html:
"click - 当同一元素上发生 mousedown 和 mouseup 事件时触发。"

http://www.w3.org/TR/DOM-Level-3-Events/#events-mouseevent-event-order
“...一般来说,当关联的 mousedown 和 mouseup 事件的事件目标是相同的元素且没有 mouseout 或 mouseleave 事件介入时,应该触发 click 和 dblclick 事件,并且应该在事件发生时在最近的共同祖先上触发 click 和 dblclick 事件关联的 mousedown 和 mouseup 事件的目标不同。”

我不是 100% 确定现在“正确”的行为实际上应该是什么(也许 IE 是唯一能够正确处理它的浏览器?)。从最后一句看来,在 body 上触发 click 事件似乎是正确的,因为 body 是两个 div 元素的“最近共同祖先”。上面引用的 w3.org 页面上还有其他一些语句,它们描述了元素被删除时的行为,但我再次不确定这是否适用于此,因为没有元素被删除,但被其他元素覆盖。

编辑 2:

@Evan 打开了一个错误报告,要求微软放弃所描述的行为:https://connect.microsoft.com/IE/feedback/details/809003/unexpected-click-event-triggered-when-the-elements-below-cursor-at-mousedown-and-mouseup-events-are-different

编辑 3:

除了 Internet Explorer,Google Chrome 最近也开始出现同样的行为:https://code.google.com/p/chromium/issues/detail?id=484655

【问题讨论】:

  • @RPM 是什么意思?
  • 这个泡菜的诡异之处在于IE处理它的方式实际上更直观
  • @LloydBanks,实际上我不是 100% 确定“正确”的行为应该是什么。我的假设是,因为在 mousedown 事件处理程序中添加了一个新层(它覆盖了原始的 click-source-element),似乎所有浏览器,除了 IE,都假设这不是对 body 的点击或不再是“clickme”-div,因为鼠标指针下方的元素发生了变化。
  • 也许有更好的方法来实现你想要做的事情。您能否对您尝试创建的 UI 进行更广泛的解释?为什么需要整个文档的点击处理程序?打开叠加层后是否需要保留文档点击事件?

标签: javascript jquery internet-explorer dom javascript-events


【解决方案1】:

我也遇到了这个问题。我决定制作一个 jQuery 插件来解决这个问题并将它放在 GitHub 上。

都在这里,欢迎反馈:https://github.com/louisameline/XClick

@mkurz :感谢您找到 W3 指令,您为我节省了很多时间。 @vitalets:我解决了这个问题,因为我像你一样使用 select2(你把我带到了这个话题)。我将 fork select2 repo 并给对此感兴趣的人留言。

我会看看是否可以让 Microsoft 人员来看看它,希望能改变这种烦人的点击行为。

【讨论】:

    【解决方案2】:

    我也为这种行为而苦恼。我已经修改了您的小提琴,以了解如何使用动态创建的叠加层触发所有鼠标事件:

    http://jsfiddle.net/Fh4sK/9/

    所以,当某个元素的 mousedown 处理程序在 mousedown 发生的同一位置显示覆盖时:
    Chrome, FF:

    1. mousedown 在元素上触发
    2. mouseup 覆盖触发
    3. click 不会触发

    IE:

    1. mousedown 在元素上触发
    2. mouseup 覆盖触发
    3. click 在 BODY(!) 上触发

    如果您在 mousedown 中隐藏遮罩,则同样的行为。

    这个问题可能会导致 IE 中出现模态、掩码、覆盖等奇怪的事情。

    有趣的事情:如果您在 mouseup 而不是 mousedown 中显示叠加层 - 一切正常

    解决方案我发现是使用mouseup而不是mousedown
    无法正常解释,因为这两个事件都是在之前click触发的。
    在这种情况下,所有鼠标事件都会在元素上触发:

    http://jsfiddle.net/Fh4sK/11/

    1. mousedown 在元素上触发
    2. mouseup 在元素上触发
    3. click 在元素上触发

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      您可以按目标过滤文档点击以排除对该 div 的点击:

      $(document).on('click', function(event) {
          if(!$(event.target).hasClass('clickme')) {
              console.log('body click');  
          }
      });
      

      【讨论】:

      • 感谢您的回答罗霍卡!但这不起作用,IE 仍然会泄漏点击事件。似乎点击事件的目标不是“clickme” div,而是正文本身......这是带有您建议的示例的更新版本:jsfiddle.net/Fh4sK/6
      【解决方案4】:

      如果你想停止点击事件的冒泡,试试这个:(我没有IE来测试)

      $(document).on('click', function(event) {
          console.log('body click');
      });
      
      $('.clickme').on('mousedown', function(event) {
          console.log('div mousedown');
      });
      
      $('.clickme').on('click', function(event) {
        event.stopPropagation();
      });
      

      Click、mousedown 和 mouseup 是不同的事件,相互独立。 here is a similar question

      【讨论】:

      • 感谢您的回复,但这也不起作用。我已经尝试过 event.stopPropagation() 以及 event.stopImmediatePropagation() 和 event.preventDefault() 以及 event.cancelBubble = true。我什至试过 event.originalEvent.cancelBubble = true。没有任何效果。我认为那是因为点击事件的来源不是“clickme” div。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-28
      • 2010-10-19
      • 1970-01-01
      • 2010-10-09
      • 2011-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多