即使在stopPropagation之后,mouseenter事件也会被调用两次

时间:2011-07-31 09:24:16

标签: javascript html javascript-events jquery

我是jquery的新手,现在面临着一个奇怪的问题。我成功地将其缩小到一个事实,即mouseenter事件被调用两次:一次用于包含div(这是我的意图),再次用于此div中的元素(不好)。我试图使用'return false'和'stopPropagation',但它似乎不起作用。 这是代码:

<!-- JS files (order matters!) -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.js"></script>


<script type="text/javascript">
$(function (){
    $(".testDiv").hover(
    function(e) /* IN */ {
        $(this).data("htmlBackup", $(this).html());
        $(this).html("TEST 123");
        e.stopPropagation();
        return false;
    }, function(e) /* OUT */ {
        $(this).html($(this).data("htmlBackup"));
        e.stopPropagation();
        return false;
    });
});         
</script>

<!-- this one works -->
<div class="testDiv" style="border: solid">ORIG HTML</div>

<br /> <br /> <br />

<!-- this doesn't work -->
<div class="testDiv" style="border: solid"> <p style="border: solid">ORIG HTML</p></div>

你也可以在这里看到它:http://jsfiddle.net/rFqyP/3/

非常感谢任何帮助!

4 个答案:

答案 0 :(得分:3)

发生的事情是mouseenter事件连续两次触发(您可以通过一些console.log调用轻松测试)。这是有问题的,因为它将更改元素的html(并使其只是“测试”字符串),然后在第二次连续运行时它将采用html并将其保存到元素的数据。但是由于没有触发mouseleave事件,如上所述,html是“测试”字符串,所以现在它将 保存到元素数据中。

之后,mouseentermouseleave事件继续触发,但元素的html及其数据都具有相同的“test”字符串,因此它不会更改。

mouseenter连续两次触发的原因是边界。 div的尺寸发生变化,因此会发生以下一系列事件:

  1. mouseenter(div变薄)
  2. mouseleave(div变得更厚,会导致几乎自动mouseenter
  3. 如在2中提到的
  4. mouseenter因为即使鼠标离开div,div也会扩展,因此鼠标进入。 mouseenter解雇后,div转到“测试”字符串,变得更薄,所以现在鼠标超出了div的边界,但没有触发{{1} }。
  5. 下次我将鼠标悬停在div上时,mouseleave将再次触发&lt; ==这是连续两次
  6. 你可以看到这种情况发生,例如,如果你用鼠标慢慢进入,上面的一些事件就不会发生,而且它实际上会按预期工作。

    顺便说一句,我不认为交换HTML内容是最好的主意。如果您想切换内容,我建议mouseenterhide()。首先,它可以保存事件处理程序,并且更直观。你有兴趣隐藏东西,而不是序列化和保存。

答案 1 :(得分:1)

您可以通过使用标记来防止代码卡住,以便您可以检测何时获得双mouseenter个事件:

$(function(){

  var inside = false;

  $(".testDiv").hover(
    function(e) /* IN */ {
      if (!inside) {
        inside = true;
        $(this).data("htmlBackup", $(this).html());
        $(this).html("TEST 123");
      }
    }, function(e) /* OUT */ {
      inside = false;
      $(this).html($(this).data("htmlBackup"));
    }
  );

});

http://jsfiddle.net/rFqyP/16/

然而,这将无法解决尺寸差异的问题。当您通过向下边框向外移动元素时,它会增长并导致mouseenter事件,这会再次更改大小,以便鼠标在外部但不会导致mouseleave事件,从而保留元素看起来像鼠标还在徘徊它。

p元素中重新定义边框可以完全解决问题,而不需要标记,因为它是导致大小差异的边框。

答案 2 :(得分:0)

我认为第二个不起作用,因为html是不同的。如果您使用相同的HTML,则根本不需要stopPropagationreturn false。看看小提琴:http://jsfiddle.net/aC3TG/1/

$(function (){
    $(".testDiv").hover(
    function(e) /* IN */ {
        $(this).data("htmlBackup", $(this).html());
        $(this).html("TEST 123");
    }, function(e) /* OUT */ {
        $(this).html($(this).data("htmlBackup"));

    });
});         

答案 3 :(得分:0)

我看到的问题(调试后)是。你有div和p所以......

当鼠标悬停在有p的div上时,首先会触发div“mouseover”事件,该事件存储整个html,包括p标记。

但在将此html写回div之前,会触发“p”鼠标悬停,用文本而不是html替换您的数据。

然后你的文字最终写到了div。