繁体   English   中英

即使鼠标未在 Chrome 上移动,也会在滚动时触发 mousemove 事件

[英]mousemove event is triggered onscroll even when mouse was not moved on Chrome

我试图通过自定义下拉列表来回答问题,但受到 Chrome 和 Firefox 中不一致行为的挑战。

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

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

重现问题:

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

问题是到达视图中的项目末尾后,它会滚动。 即使鼠标未触动,它也会在 Chrome 中触发mouseentermousemove事件。 在 FF 中,滚动时它只触发有意义的mouseenter

在此处输入图片说明

问题):

  • 为什么鼠标不动时会触发mousemove
  • 这只是浏览器不一致吗? 找不到有关滚动时触发的事件的文档? (从来不知道是这样)

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

在您的示例中,我看到每当鼠标悬停在<ul>时,Chrome 和 FF 都会触发mouseenter DOM 事件并按下键触发浏览器滚动以使所选<li>进入视图。

但是,只有 Chrome 会另外触发mousemove事件。 两个抛出的mouseenter事件对象中已经存在的一个明显区别是,对于 Chrome,包含MouseEvent.offsetXMouseEvent.offsetY值,而在 FF 中,这些属性是undefined 所以,当那个 enter 被触发时,Chrome 已经决定鼠标“已经移动”了。

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

DOM 事件规范

mousemoveDOM 级别 2 事件规范如下:

当指针设备在元素上移动时发生 mousemove 事件。

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

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

似乎这可能取决于人们是否相对地解释“被移动”。

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

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

编辑:

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

进一步编辑:

似乎您发现了一个错误,即可能不应该在 chrome 中触发 mousemove。 如果你对它进行了足够的破解,可能会有一些解决方法。 但最好的解决方案可能只是避免在这种情况下使用 mousemove。 通常,mousemove 是那些昂贵的事件之一,只有在您真正需要它时才应该使用它。

这是一个很好的演示。 在 Chrome 中,元素的鼠标移动绝对是​​相对的。 在 chrome 中,只有当鼠标指针位于滚动条上时,我才能获得 keydown 和滚动事件。 如果我使用滚轮滚动并将鼠标悬停在滚动条上,我也可以获得仅滚动事件。 通过拖动滚动会导致“鼠标移动”和“鼠标悬停”事件,这并不奇怪。

浏览器不仅会大量产生鼠标移动和鼠标悬停事件,它们也不能很好地表明用户的意图。 事实上,这些事件是有用的熵源。 在某种程度上存在一些细微差别,这是在这些“微事件”单独有用的情况下。 要与它们合作,您必须设计一种方法来过滤它们,以满足您想要链接到更高级别操作的用户意图。 您选择来理解这些事件的任何合理方法都可能将这些移动 - 滚动事件检测为垃圾。 这是您的观点真正值得注意和惊慌失措的地方。 第一阶段是根据坐标的元素和值过滤掉事件。 它可能有助于创建状态机模型。 您可以注册和注册处理程序以响应其他事件。 您已经确定了这种情况,如果关键元素具有滚动条,则您希望更改响应状态或响应标准。 如果元素或其父元素具有垂直滚动条,则会抛出具有相对较高 X 值的鼠标移动。

如果在该上下文中通过鼠标移动触发鼠标悬停,您可能还想忽略鼠标悬停。 即使您通过注册或取消注册处理程序来更改状态,一次处理每个微事件也开始变得不切实际。 可以通过创建事件序列 fifo 缓冲区来提取更多信息。 注册事件处理程序以向缓冲区添加新事件。 您可能还希望从此缓冲区中的计时器事件收集信息以建立更多上下文。 您可能会创建一个将 fifo 保存在数组中的对象。 这就像一个队列,但并不是说它是一个等待处理事件的地方。 相反,您的程序正在等待计算缓冲区中的模式,并根据模式触发更高级别的事件,接受或拒绝不同类型的事件并扩展、收缩或保存缓冲区的内容。 然后,您可以评估 x 和 y 变化的移动事件,并根据您演示的鼠标滚动和鼠标移动事件的模式创建条件。

这不是一个错误。 mousemove 是相对于事件附加到的元素。 在您的情况下,您看到鼠标没有移动,因为您将浏览器窗口作为参考。 但是对于那个滚动列表,每当列表滚动时,鼠标指向列表的某个元素移动到不同的元素

想象你是地球,一杯咖啡像鼠标一样站在桌子上,可滚动列表像太阳:如果你(窗口)不动,那杯咖啡(鼠标)的位置在同一个地方给你; 但是对于太阳(列表),它会看到地球和咖啡杯都在移动。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM