为什么mouseout处理程序在这种情况下表现得如此不合逻辑?

时间:2017-05-21 11:07:27

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

红色方块是容器的一部分,类为#34; parent"。如果我将鼠标悬停在该红色方块上,它就会消失。但为什么?我希望它不应该。

预期的行为:它不会消失,因为红色方块是" .parent"的一部分。容器,我已经明确指出,mouseout事件发生在该容器上。

有人建议,这个问题是

的重复

JavaScript mouseover/mouseout issue with child element

在某种程度上 - 是的,但我认为这个问题提供了价值,因为它不仅提供了解决方案("你可以试试这个"),还解释为什么你应该使用它以及为什么初始解决方案没有按预期工作。



<span class="parent">Hover mouse over this text<br></span>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
    function removeSquare()
    {
        $(this).find(".kvadrat").remove();
    }

    function addSquare()
    {
        $(this).append("<span style='display:inline-block;width: 50px;height: 50px;background-color:red' class='kvadrat'></span>");
        $(this).on("mouseout", removeSquare);
    }
    $(".parent").on("mouseover", addSquare);
</script>
&#13;
&#13;
&#13;

5 个答案:

答案 0 :(得分:11)

这是.mouseout()事件的正常行为。

  

显示mouseout和mouseleave事件被触发的次数。   当指针移出子元素时,mouseout会触发   好吧,只有当指针移出时,mouseleave才会触发   绑定元素。

您应该使用.mouseenter().mouseleave()个事件,

function removeSquare()
{
$(this).find(".kvadrat").remove();
}

function addSquare()
{
    $(this).append ( "<span style='display:inline-block;width: 50px;height: 50px;background-color:red' class='kvadrat'></span>" );
    
}
$ ( ".parent" ).on ( "mouseenter", addSquare );
$(".parent").on("mouseleave", removeSquare);
.parent {
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="parent">Hover mouse over this text<br></span>

答案 1 :(得分:6)

正如其他人所说,您最初的问题是mouseovermouseout事件也会触发子元素。该问题的解决方案是使用jQuery的mouseentermouseleave事件,或者只是用CSS :hover pseudo-class替换JS代码。

然而,其他JS和CSS解决方案在这里发布的原因有时会表现得不正常(如果你慢慢地将鼠标移到它上面会导致方块消失,但如果你快速移动它就不会消失,而不是在所有浏览器上,即使你慢慢移动)是因为,根据您的浏览器和字体设置,文本的顶行与其下方的正方形之间可能存在或可能没有小差距。如果存在间隙,并且鼠标光标在从文本移动到正方形时触及它,则浏览器会认为鼠标已离开父元素,因此将隐藏正方形。

在父元素上设置(浅蓝色)背景颜色可以清楚地显示问题;根据浏览器选择的字体和行高,父元素和框可以如下所示:

Screenshot (small line height, no gaps between lines)

或者像这样:

Screenshot (large line height with gaps between lines)

手动设置特别大的线条高度使问题易于重现(基于Thomas van Broekhoven's answer的CSS示例):

.kvadrat {
  display: none;
}
.parent:hover > .kvadrat {
  display: inline-block;
  background-color: red;
  width: 50px; height: 50px;
}
.parent {
  line-height: 2.0;
  background: lightblue;
}
<span class="parent">Hover mouse over this text!<br>
Here's another line of text.<br>
<span class='kvadrat'></span></span>

有两种解决此问题的常规方法。在可行的情况下,最简单的选择是使父元素成为块,从而消除线之间的间隙。您可能还希望将position: absolute添加到正方形的样式中,以便在出现时不会展开其父元素:

.kvadrat {
  display: none;
}
.parent:hover > .kvadrat {
  display: inline-block;
  position: absolute;
  background-color: red;
  width: 50px; height: 50px;
}
.parent {
  display: block;
  line-height: 2.0;
  background: lightblue;
}
<span class="parent">Hover mouse over this text!<br>
Here's another line of text.<br>
<span class='kvadrat'></span></span>

或者,如果你真的想坚持使用内联父元素(例如,因为你希望它能够包裹几行文本),你可以在正方形上设置一个负的上边距,以确保它与重叠它上面的文字行。如果你不希望方格明显地重叠文本,你可以进一步将方块的所有可见内容移动到内部元素中并在其上设置相应的正上边距,如下所示: / p>

.kvadrat {
  display: none;
}
.parent:hover > .kvadrat {
  display: inline-block;
  position: absolute;
  margin-top: -1em;
  border: 1px dashed gray; /* to show the extent of this otherwise invisible element */
}
.kvadrat > .inner {
  display: block;
  margin-top: 1em;
  background-color: red;
  width: 50px; height: 50px;
}
.parent {
  line-height: 2.0;
  background: lightblue;
}
<span class="parent">Hover mouse over this text!<br>
Here's another line of text.<br>
<span class='kvadrat'><span class='inner'></span></span></span>

答案 2 :(得分:5)

我知道这不是直接回答您的JavaScript问题,但如果您不受JavaScript限制,我想睁开眼睛。您可以使用 CSS 轻松实现此目的。

&#13;
&#13;
.kvadrat {
  display: none:

}
.parent:hover > .kvadrat {
  display: inline-block;
  background-color: red;
  width: 50px;height: 50px;
}
&#13;
<span class="parent">Hover mouse over this text<br>
<span class='kvadrat'></span></span>
&#13;
&#13;
&#13;

答案 3 :(得分:1)

您可以使用CSS实现相同的目标。

.child {
  display: none:
  
}
.parent:hover > .child {
  display: inline-block;
  background-color: red;
  width: 50px;
  height: 50px;
}
<span class="parent">Hover mouse over this text<br>
  <span class='child'></span>
</span>

答案 4 :(得分:0)

这是因为事件冒泡。当您输入子跨度时,jQuery将触发mouseout,因为您现在已经进入子跨度。如果你想继续下去,请使用mouseenter和louseleave,直到离开实际元素时才会触发,无论子元素如何。

<span class="parent">Hover mouse over this text<br></span>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
function removeSquare()
{
$(this).find(".kvadrat").remove();
}

function addSquare()
{
    $(this).append ( "<span style='display:inline-block;width: 50px;height: 50px;background-color:red' class='kvadrat'></span>" );
    $(this).on("mouseleave", removeSquare);
}
$ ( ".parent" ).on ( "mouseenter", addSquare );
</script>