【问题标题】:Jquery mouseenter() vs mouseover()jQuery mouseenter() 与 mouseover()
【发布时间】:2011-11-09 08:02:01
【问题描述】:

所以在阅读了最近回答的question 之后,我不清楚我是否真的理解mouseenter()mouseover() 之间的区别。帖子说

MouseOver():

将在进入元素时以及任何鼠标移动时触发 发生在元素内。

MouseEnter():

在输入元素时触发。

我想出了一个使用两者的fiddle,它们似乎非常相似。谁能给我解释一下这两者的区别?

我也尝试过阅读 JQuery 定义,两者都说同样的话。

当鼠标指针进入元素时,鼠标悬停事件被发送到元素

当鼠标指针进入元素时,mouseenter 事件被发送到元素。

有人可以举例说明一下吗?

【问题讨论】:

标签: jquery dom-events


【解决方案1】:

查看jquery文档页面底部的示例代码和演示:

http://api.jquery.com/mouseenter/

...当指针移入子元素时触发鼠标悬停 好吧,而 mouseenter 仅在指针移入时触发 绑定元素。

【讨论】:

    【解决方案2】:

    当您的目标元素包含子元素时,您会看到该行为:

    http://jsfiddle.net/ZCWvJ/7/

    每次您的鼠标进入或离开子元素时,都会触发mouseover,但不会触发mouseenter

    $('#my_div').bind("mouseover mouseenter", function(e) {
      var el = $("#" + e.type);
      var n = +el.text();
      el.text(++n);
    });
    #my_div {
      padding: 0 20px 20px 0;
      background-color: #eee;
      margin-bottom: 10px;
      width: 90px;
      overflow: hidden;
    }
    
    #my_div>div {
      float: left;
      margin: 20px 0 0 20px;
      height: 25px;
      width: 25px;
      background-color: #aaa;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
    
    <div>MouseEnter: <span id="mouseenter">0</span></div>
    <div>MouseOver: <span id="mouseover">0</span></div>
    
    <div id="my_div">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>

    【讨论】:

    • @psychobrm - 不。玩这两个也跟踪mouseleave 事件的演示:jsfiddle.net/ZCWvJ/232jsfiddle.net/ZCWvJ/233 如果在与进入+离开相同的地方,那么结束的计数将是进入和离开的计数总和。
    • var n = + el.text();而不是var n = el.text();有什么具体原因吗?我只是出于好奇。
    • @FredrickGauss - 我正在使用+ 运算符将el.text() 返回的字符串强制转换为数字。我需要吗?不会。在这种情况下,使用n 的下一条语句也会将其强制转换为数字。那么,为什么我使用它?我不确定……这是两年前的事了。这是一个好习惯。它使我的意图明确。可能我在保存之前最初有n + 1,但决定将我的代码缩小2个字符并只使用++nn + 1不会n强制转换为一个数字,而是将1强制转换为一个字符串,从而导致输出,例如0111111
    • @gilly3 - 感谢您详细解释您在脑海中的旅行。
    • @gilly3 很好的总结,但有一个小的改进:“或者离开一个子元素”应该是“或者离开一个子元素,因为子元素和父元素之间存在差距。你的小提琴有一个边距/内边距,因此当您离开子元素时,您确实会收到鼠标悬停事件,但尝试不使用内边距/边距时,您将不会收到此事件。
    【解决方案3】:

    尽管它们的操作方式相同,但mouseenter 事件仅在鼠标指针进入所选元素时触发如果鼠标指针也进入任何子元素,则会触发mouseover 事件。

    【讨论】:

      【解决方案4】:

      mouseenter 事件在处理事件冒泡 的方式上不同于 mouseovermouseenter 事件,仅在 鼠标进入其绑定的元素触发其处理程序,不是后代 . 参考:https://api.jquery.com/mouseenter/

      mouseleave 事件不同于 mouseout 处理事件冒泡 的方式。 mouseleave 事件,仅在 鼠标离开它所绑定的元素触发其处理程序,不是后代 . 参考:https://api.jquery.com/mouseleave/

      【讨论】:

        【解决方案5】:

        此示例演示了 mousemovemouseentermouseover 事件之间的区别:

        https://jsfiddle.net/z8g613yd/

        HTML:

        <div onmousemove="myMoveFunction()">
            <p>onmousemove: <br> <span id="demo">Mouse over me!</span></p>
        </div>
        
        <div onmouseenter="myEnterFunction()">
            <p>onmouseenter: <br> <span id="demo2">Mouse over me!</span></p>
        </div>
        
        <div onmouseover="myOverFunction()">
            <p>onmouseover: <br> <span id="demo3">Mouse over me!</span></p>
        </div>
        

        CSS:

        div {
            width: 200px;
            height: 100px;
            border: 1px solid black;
            margin: 10px;
            float: left;
            padding: 30px;
            text-align: center;
            background-color: lightgray;
        }
        
        p {
            background-color: white;
            height: 50px;
        }
        
        p span {
            background-color: #86fcd4;
            padding: 0 20px;
        }
        

        JS:

        var x = 0;
        var y = 0;
        var z = 0;
        
        function myMoveFunction() {
            document.getElementById("demo").innerHTML = z += 1;
        }
        
        function myEnterFunction() {
            document.getElementById("demo2").innerHTML = x += 1;
        }
        
        function myOverFunction() {
            document.getElementById("demo3").innerHTML = y += 1;
        }
        
        • onmousemove :每次鼠标指针移到 div 元素上时发生。
        • onmouseenter :仅在鼠标指针进入 div 元素时发生。
        • onmouseover :当鼠标指针进入 div 元素时发生, 及其子元素(p 和 span)。

        【讨论】:

        • jsfiddle 不知何故坏了,说功能未定义 - 我只是将所有 js 分叉并移动到 &lt;script&gt; jsfiddle.net/orc8empd
        【解决方案6】:

        老问题,但在 imo 洞察力中仍然没有很好的最新答案。

        由于 jQuery 对事件和处理程序使用 Javascript 措辞,但对这些事件和处理程序有自己的未记录但不同的解释,让我首先阐明与纯 Javascript 观点的区别:

        • 两个事件对
          • 当移动速度快于浏览器对其位置的采样速度时,鼠标可以从外部/外部元素“跳转”到内部/最内部元素
          • 任何enter/over 都会获得相应的leave/out(可能迟到/跳跃)
          • 事件转到指针下方的可见元素(不可见元素不能成为目标)
        • mouseenter/mouseleave
          • 不会冒泡(事件对委托处理程序无用)
          • 事件注册本身定义了观察和抽象的区域
          • 在目标区域工作,就像一个带池塘的公园:池塘被认为是公园的一部分
          • 每当元素本身或任何直接的后代第一次进入/离开时,都会在目标/区域上发出事件
          • 进入后代、从一个后代移动到另一个后代或返回目标不会完成/重新启动 mouseenter/mouseleave 循环(即没有触发事件)
          • 如果您想使用一个处理程序观察多个区域,请在每个区域/元素上注册它或使用接下来讨论的另一个事件对
          • 注册区域/元素的后代可以有自己的处理程序,创建一个独立的观察区域,具有独立的mouseenter/mouseleave 事件周期
          • 如果你想一下mouseenter/mouseleave 的冒泡版本会是什么样子,你最终会得到类似mouseover/mouseout 的东西
        • mouseover/mouseout
          • 事件气泡
          • 只要指针下方的元素发生变化,就会触发事件
            • mouseout 在先前采样的元素上
            • 后跟 mouseover 在新元素上
            • 事件不会“嵌套”:例如之前孩子“过度”了,父母会“出局”
          • target/relatedTarget 表示新元素和上一个元素
          • 如果你想看不同的区域
            • 在一个共同的父级(或多个父级,它们一起涵盖您要观看的所有元素)上注册一个处理程序
            • 在处理程序元素和目标元素之间寻找您感兴趣的元素;也许$(event.target).closest(...) 适合您的需求

        不那么平凡的mouseover/mouseout 示例:

        $('.side-menu, .top-widget')
          .on('mouseover mouseout', event => {
            const target = event.type === 'mouseover' ? event.target : event.relatedTarget;
            const thing = $(target).closest('[data-thing]').attr('data-thing') || 'default';
            // do something with `thing`
          });
        

        如今,所有浏览器都原生支持mouseover/mouseoutmouseenter/mouseleave。尽管如此,jQuery 不会将您的处理程序注册到 mouseenter/mouseleave,而是将它们默默地放在 mouseover/mouseout 周围的包装器上,如下面的代码所示。

        模拟是不必要的、不完美的并且浪费 CPU 周期:它过滤掉了 mouseenter/mouseleave 无法获得的 mouseover/mouseout 事件,但 target 却是一团糟。真正的 mouseenter/mouseleave 会将处理程序元素作为目标,模拟可能指示该元素的子元素,即 mouseover/mouseout 携带的任何内容。

        出于这个原因,我不对这些事件使用 jQuery,但是例如:

        $el[0].addEventListener('mouseover', e => ...);
        

        const list = document.getElementById('log');
        const outer = document.getElementById('outer');
        const $outer = $(outer);
        
        function log(tag, event) {
          const li = list.insertBefore(document.createElement('li'), list.firstChild);
          // only jQuery handlers have originalEvent
          const e = event.originalEvent || event;
          li.append(`${tag} got ${e.type} on ${e.target.id}`);
        }
        
        outer.addEventListener('mouseenter', log.bind(null, 'JSmouseenter'));
        $outer.on('mouseenter', log.bind(null, '$mouseenter'));
        div {
          margin: 20px;
          border: solid black 2px;
        }
        
        #inner {
          min-height: 80px;
        }
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        
        <body>
          <div id=outer>
            <ul id=log>
            </ul>
          </div>
        </body>

        注意:对于委托处理程序,永远不要使用 jQuery 的“带有选择器注册的委托处理程序”。 (原因在another answer。)使用这个(或类似的):

        $(parent).on("mouseover", e => {
          if ($(e.target).closest('.gold').length) {...};
        });
        

        而不是

        $(parent).on("mouseover", '.gold', e => {...});
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多