【问题标题】:MouseEnter event does not fire when entering parent from child element从子元素进入父元素时,MouseEnter 事件不会触发
【发布时间】:2017-01-19 15:16:33
【问题描述】:

我的 HTML 看起来像这样:

<div id="parent">
  <div class="child">
    Child 1
  </div>
  <div class="child">
    Child 2
  </div>
  <div class="child">
    Child 3
  </div>
</div>

我像这样附加 mouseenter 和 mouseout 事件:

$("*").on("mouseenter", function() {
    $(this).addClass("mouse_over");
});

$("*").on("mouseout", function() {
    $(this).removeClass("mouse_over");
});

现在,想象以下鼠标事件序列:

  1. 我将鼠标移到父 div 中。正如预期的那样,mouseenter 事件触发,并且 mouse_over 类被放在父级上。
  2. 我搬进了其中一个孩子。 mouseout 事件为父级触发,而 mouseenter 事件为子级触发。很好。
  3. 我将鼠标移回父级。 mouseenter 不会在这里触发。

第三步是这里的问题。当从子元素重新进入父级时,我希望将 mouse_over 类放回父级。

我想我明白为什么会发生这种情况,因为从技术上讲,我的鼠标一直在父级中,所以触发 mouseenter 事件没有意义。

这是一个更好地说明我正在尝试做的事情的小提琴:

https://jsfiddle.net/tg1wg1xx/

如果您将鼠标悬停在父元素和子元素中,您会在离开时注意到图案叠加层并未放置在父元素上。

那么如何确保叠加层始终放置在我当前悬停的任何元素上?

【问题讨论】:

  • 这就是你想要的吗? jsfiddle.net/tg1wg1xx/7
  • @Karl-AndréGagnon 是的,这正是我想要的!发布答案,我会接受。

标签: javascript jquery html events dom-events


【解决方案1】:

作为Boris explained in his answer,有两个不同的事件。引用他的话:

  • mouseenter 和 mouseleave 在您进入和离开节点层次结构时触发,但在您导航该层次结构的后代时不会触发。
  • mouseover 和 mouseout 分别在鼠标进入和离开节点的“独占”空间时触发,因此当鼠标进入子节点时,您会得到“退出”。

话虽如此,您需要mouseover 和mouseout,因为您需要在悬停儿童时触发鼠标。

$("*").on("mouseover", function(e) {
    $(this).addClass("mouse_over");
});

$("*").on("mouseout", function(e) {
    $(this).removeClass("mouse_over");
});

接下来,您需要知道树中的事件气泡。所以当你mouseover一个孩子时,这个事件也会传播给父母。这就是为什么即使悬停子项,父项也处于悬停状态。

要解决这个问题,您需要在事件对象上使用.stopPropagation()。

$("*").on("mouseover", function(e) {
    $(this).addClass("mouse_over");
    e.stopPropagation();
});

$("*").on("mouseout", function(e) {
    $(this).removeClass("mouse_over");
    e.stopPropagation();
});

See it in action


奖金

本着少写代码的精神,您也可以使用它:

$("*").on("mouseover mouseout", function(e) {
    $(this).toggleClass("mouse_over");
    e.stopPropagation();
});

【讨论】:

    【解决方案2】:

    javascript 中的鼠标事件可能会让人迷失方向。请注意,有两对事件的含义不同:

    • mouseenter 和 mouseleave 在您进入和离开节点层次结构时触发,但在您导航该层次结构的后代时不会触发。
    • mouseover 和 mouseout 在鼠标分别进入和离开节点的“独占”空间时触发,因此当鼠标进入子节点时,您会得到“退出”。

    您观察到的行为是因为您将两者混合在一起:我在https://jsfiddle.net/drxrea7e/1/ 更新了您的小提琴以使用进入和离开。

    您可以参考活动的documentation on mozilla's site了解详细信息。

    在您发表评论后编辑:啊,那么我们需要另一件事:

    事件实际上是冒泡的,所以父级也接收到它(但目标 = theChild)。因此,仅当 event.target == this 时才想添加该类:请参阅我的新版本小提琴:https://jsfiddle.net/drxrea7e/3/。

    孩子们从 .mouse_over 类中获取图像,从 .parent 中获取红色,因为 background:url() 覆盖了 background-color:white。这是你的预期吗?

    【讨论】:

    • 哇,我从事 Web 开发多年,从不知道有两个不同的事件,所以感谢您指出这一点。不幸的是,你的小提琴仍然没有完全符合我的要求。在您的小提琴中,当您将鼠标悬停在子元素中时,父元素仍然“突出显示”。我希望在这种情况下突出显示子元素。我将阅读事件的文档,看看是否能找到解决方案,但感谢您指出我的幼稚。
    • 嘿,我确实认为这些名称非常令人困惑,所以不要太天真:)。请参阅我关于冒泡的编辑。 stopPropagation() 也可以,但我不喜欢它,因为它可能会破坏层次结构上下的其他行为。
    【解决方案3】:

    对您的代码进行了一些更新,以使其按您的意愿工作。

    $("*").on("mouseover", function(e) {
    	$(this).addClass("mouse_over");
      e.stopPropagation();
    });
    
    $("*").on("mouseout", function(e) {
    	$(this).removeClass("mouse_over");
      e.stopPropagation();
    });
    #parent {
      padding: 24px;
      background-color:red;
    }
    
    .child {
      padding: 6px;
      background-color:white;
    }
    
    .mouse_over {
        background:url( data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAIUlEQVQYV2NkYGBIY2BgmMUABYxQGi4IEwCJgwWRBcCCAHscA2vMYjzKAAAAAElFTkSuQmCC
        ) repeat !important;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="parent">
      <div class="child">
        Child 1
      </div>
      <div class="child">
        Child 2
      </div>
      <div class="child">
        Child 3
      </div>
    </div>

    【讨论】:

    • Binod,这确实符合我的要求,谢谢。然而,卡尔首先在评论中提供了一个解决方案,所以我将给他一些时间自己添加一个回复。但再次感谢您的帮助。
    • 没关系@thatidiotguy。您实际上可以要求他发布他的答案,
    猜你喜欢
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 2013-02-23
    • 2013-12-28
    • 1970-01-01
    • 2018-10-21
    • 2017-12-05
    • 1970-01-01
    相关资源
    最近更新 更多