即使没有在chrome上移动鼠标,也会触发onmroll上的mousemove事件

Sel*_*gam 27 javascript firefox webkit google-chrome javascript-events

我试图回答自定义下拉菜单的问题,但是Chrome和FF中的行为不一致.

演示: http ://jsfiddle.net/fyeht/ [添加滚动事件以获得更清晰]

请参见下图,可以使用箭头键导航列表项.

要重现此问题:

  1. 在Chrome中打开控制台(F12)
  2. 单击列表中的项目(您会注意到在控制台中记录了一些事件)
  3. 使用向下箭头键导航到列表中的下一个项目
  4. 最后,当您到达视图中的最后一个项目并且按下向下箭头时,会注意到该问题.检查日志以查看"滚动","鼠标输入"和"鼠标移动"[查看新演示]

问题是在到达视图中的项目结束后,它会滚动.即使鼠标未受影响,它也会在Chrome中触发mouseenter和触发mousemove事件.在FF中,在滚动时它会触发mouseenter哪个有意义.

在此输入图像描述

问题(S):

  • mousemove鼠标未受影响时为什么会触发?
  • 这只是浏览器的不一致吗?无法找到滚动时触发的事件的文档?(从来不知道它确实如此)

提交了错误报告:https://code.google.com/p/chromium/issues/detail?id = 241476

mer*_*erv 10

在您的示例中,我看到Chrome和FF 都会在鼠标悬停在鼠标上时触发mouseenter DOM事件<ul>,按下键会触发浏览器滚动以将选定项<li>置于视图中.

但是,只有Chrome会另外触发mousemove事件.在mouseenter事件对象中已经存在一个明显的区别,即两次抛出是针对Chrome的,MouseEvent.offsetX并且MouseEvent.offsetY包含值,而在FF中这些属性是undefined.因此,当触发该输入时,Chrome已经确定鼠标"已移动".

由于MouseEvent.screenXMouseEvent.screenY事件上下文值在滚动触发的MouseEvent实例之间不会改变,因此可以通过存储来自先前事件的这些值来区分"人工" mouseenter/mousemove事件和"真实"事件.

DOM事件规范

mousemoveDOM Level 2事件规范读取:

当指针设备在元素上方移动时,会发生mousemove事件.

3级规范(工作草案)基本上是一样的:

当指针设备在元素上移动时,用户代理必须调度此事件.

似乎可以归结为一个人是否相对地解释"被移动".

此外,在关于鼠标事件顺序的Level 3规范部分中,它指出当指针移动到元素中时,它会按顺序触发mouseover,mouseentermousemove.在那里指定的每个案例总是将这三个组合在一起,所以也许有人可能会解释它如果你要触发mouseenter事件,你也应该触发对应于输入元素的mousemove事件.

  • 这个测试是否是一个线索:https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/LayoutTests/fast/events/frame-scroll-fake-mouse-move.html?(另请参见overflow-scroll -...)它似乎是在滚动时明确检查mousemove(mouseover,really)事件.(可能相关:有一条评论说"WebKit安排假鼠标移动事件作为在窗口中安装WebView的一部分......".该测试也被报告为片状:https://bugs.webkit.org /show_bug.cgi?id=103043.不确定这有多少是有用的信息.) (2认同)

Rin*_*ngo 1

我真的怀疑这里存在浏览器不一致的情况。您应该创建一个 mousemove 事件来打印 x 和 y 坐标。您可能会看到鼠标确实移动了一点。如果是这种情况,请尝试使用插件hoverIntent来消除此类问题。

编辑:

使用向上和向下箭头键,我现在可以重现该问题。是的,它看起来确实像是某种错误!我敢打赌鼠标移动坐标增量很小。也许光标移动了一两个像素?我想说,要克服这个问题,请向 mousemove 函数添加一个检查,将先前 mousemove 的 xy 坐标与当前 mousemove 的 xy 坐标进行比较。确定它是否不仅仅是几个像素。如果是这样,您就知道这是真正的鼠标移动。如果较少,您可以将其视为 chrome bug。

进一步编辑:

看来您发现了一个错误,其中 mousemove 在 chrome 中被触发,而它可能不应该被触发。如果你破解得足够多,也许你可以找到解决方法。但最好的解决方案可能就是避免在这种情况下使用 mousemove。一般来说,mousemove 是那些昂贵的事件之一,只有在真正需要时才应该使用它。