【问题标题】:Why does Firefox fire a mouseenter event on page load?为什么 Firefox 在页面加载时会触发 mouseenter 事件?
【发布时间】:2017-07-11 12:23:03
【问题描述】:

当悬停在一个元素上然后刷新页面时(不移动鼠标):

  • Chrome 不会在页面加载时触发 mouseenter 事件
  • Firefox 在页面加载时触发 mouseenter 事件

下面是一个示例 sn-p。要重现此问题,请将鼠标悬停在 div 上,然后刷新页面。在 Chrome 中,div 不包含“mouseenter”。在 Firefox 中,确实如此。

请注意,这在 Stacksn-ps 环境中不起作用,因为您需要先单击“运行 sn-p”。 JSFiddle:https://jsfiddle.net/9fu6cx5d/7/

let div = document.getElementById('my-div');

div.addEventListener('mouseenter', function () {
  div.innerHTML = 'mouseenter';
});
#my-div {
  width: 150px;
  height: 150px;
  background-color: #aaaaaa;
}
<div id="my-div">
</div>

哪个浏览器的行为正确?我如何才能解决行为上的差异,或者至少让它们的行为相同?

Chrome 版本:59.0.3071.115(官方版本)(64 位)

Firefox 版本:54.0(64 位)

【问题讨论】:

  • 如果您将焦点放在“运行”按钮上,将鼠标移动到下方区域,然后使用回车键激活,则可以在此处演示该行为。
  • The mouseenter event is fired when a pointing device (usually a mouse) is moved over the element that has the listener attached. 根据文档,Chrome 是具有正确行为的那个。至于解决方法,也许可以在准备好的文档中尝试一下?
  • 我在 React 组件中遇到了这个问题。 mouseenter 导致重新渲染,这导致 mouseenter 事件,等等循环和崩溃的应用程序。有更新吗?如何防止页面重新加载触发 mouseenter 事件?

标签: javascript google-chrome firefox dom-events


【解决方案1】:

正如 cmets 中所指出的,根据规范,Chrome 的行为是正确的。以下是关于如何解决差异的想法。

您可以通过在文档加载时检查鼠标是否在 div 的边界内来确保您获得正确的值。不幸的是,在 JS 中没有办法在不触发事件的情况下检查鼠标位置,因此您将不得不求助于一些涉及 CSS 悬停规则并在 $(document).ready 上检查它们的技巧。

引用this hilarious answer

用覆盖整个文档的 div 覆盖您的页面。里面 那,创建(比如说)2,000 x 2,000 个元素(这样 :hover 伪类将在 IE 6 中工作,请参阅),每个 1 像素大小。创建一个 CSS:那些改变属性的元素的悬停规则(让我们 说字体系列)。在您的负载处理程序中,循环遍历 4 个 百万个元素,检查 currentStyle / getComputedStyle() 直到 您会找到带有悬停字体的那个。从此推断 元素来获取文档中的坐标。

注意不要这样做。

虽然您绝对不应该这样做,但如果您只需要解决浏览器的怪癖,那么使用无效的悬停样式来检查元素是否悬停而不需要 JS 事件的一般想法是一个很好的想法。我在下面的示例中使用font-weight,但您可以将其更改为适合您的任何内容。

CSS

#my-div:hover {font-weight:700;}

js

// Pseudocode!

var mouseIsInside = false,
    div = $('#my-div');

$(document).ready(function(){
    if (div.css('font-weight') === 700) {
        mouseIsInside = true;
    }

    doStuffIfMouseInside();
});

div.on('mouseenter', function(){
    mouseIsInside = true;
    doStuffIfMouseInside();
})

function doStuffIfMouseInside() {
    if (mouseIsInside) {
        ...
    }
}

【讨论】:

  • Chrome 的行为肯定不是正确的,它们甚至与自己不一致,请参阅this fiddle,其中添加了一个新节点,如果鼠标处于活动状态,则 mouseenter 事件将在该节点上触发首先在文档上。即使是 :hover hack 也不起作用,因为它们只是懒于在页面加载时检查鼠标状态,并且在鼠标处于活动状态之前根本不会标记 :hovered 元素。
【解决方案2】:

如果您在代码周围添加(function(){})();,它似乎在两种浏览器中都有效。

似乎 firefox 可能在 dom 可用之前触发事件,从而导致 mousein/out 事件出现问题。

见:https://jsfiddle.net/9fu6cx5d/8/

【讨论】:

  • 嗯,这可能是一种解释。但是,对我来说这没有任何区别:/
  • 你的实现中还有这些 JS 吗?我在 Firefox 54.0 和 54.0.1 中进行了测试,对我来说效果很好。
  • 没有更多的 JS - 我只是运行您链接的 sn-p 并执行相同的操作。不过,这似乎很奇怪。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 2012-05-05
相关资源
最近更新 更多