【问题标题】:jquery hover() mouseOut event not firing when mouse is moved quickly over link当鼠标在链接上快速移动时,jquery hover() mouseOut 事件不会触发
【发布时间】:2010-12-29 18:11:31
【问题描述】:

我有一个简单的链接列表,当您将鼠标悬停在它上面时,它会附加一个 div(从 XML 加载此 div 中的数据),并且在悬停时它会删除 div,但只有当鼠标在链接上缓慢移动时才会发生这种情况鼠标在链接上的移动速度比平时更快,然后它不会删除 div,这意味着没有触发 mouseout 事件

在前两个链接上用力移动鼠标,然后您会看到 div 有时不会隐藏

这是我的演示链接http://ukcatonline.com/template/

这是我的代码:

$(document).ready(function () { 

//vertical navigation js
$(".mainnav_v a").hover(
    function (e) {
        $this = $(this)
        $this.stop().animate({  paddingLeft : '16px'}, 300);

        var brand ="";
        var category="designer_frames";
        $this.each(function() 
        {
            var title = this.title;
            if ($this.is('a') && $this.attr('title') != '' && $this.attr('id')==category)
            {  
                brand= this.title;

                $.ajax({
                    type: "GET",
                    url: "xml/peek_menu.xml",
                    //ie bug : it send wrong datatype on localmachine
                    dataType: ($.browser.msie) ? "text" : "xml",
                    success: function(data) {
                        var xml;
                         if (typeof data == "string") {
                           xml = new ActiveXObject("Microsoft.XMLDOM");
                           xml.async = false;
                           xml.loadXML(data);
                         } else {
                           xml = data;
                         }
                        //could have used $(xml).find(category).each(function() but jquery is intelligent enough to know wat element is currently selected
                        $(category, xml).each(
                            function(){
                                $(brand,this).each(
                                    function(){
                                        var title = $(this).attr('title');
                                        var imgurl = $(this).attr('imgurl');
                                        var description = $(this).find('description').text();
                                        var feature1 = $(this).find('feature1').text();
                                        var feature2 = $(this).find('feature2').text();
                                        var feature3 = $(this).find('feature3').text();
                                        var feature4 = $(this).find('feature4').text();

                                        var html =  '<div id="peek_container"><img src="' + imgurl + '" alt="" /><br /><br /><h1>'+title+'</h1><br />';
                                        html += '<p>' + description + '</p><br />';
                                        html += '<ul><li>'+feature1+'</li><li>'+feature2+'</li><li>'+feature3+'</li><li>'+feature4+'</li></ul><br /></div>';
                                        $this.parent().append(html);
                                    }
                                );
                            }
                        );
                    }
                }
                );

            }
        });

    },
    function (e) {
        $this = $(this);
        $this.stop().animate({  paddingLeft : '6px' }, 300);
        $this.siblings().remove();
    }
);});

这是我的 HTML:

<ul class="mainnav_v">
  <li><a href="#url" class="peek" title="Boss" id="designer_frames">Boss</a></li>
  <li><a href="#url" title="Burberry" id="designer_frames">Burberry</a></li>
  <li><a href="#url" title="Bvlgari" id="designer_frames">Bvlgari</a></li>
  <li><a href="#url">Chanel</a></li>
  <li><a href="#url">Diesel</a></li>
  <li><a href="#url">Dior</a></li>

【问题讨论】:

  • 你用的是什么浏览器?在 IE8 和 Chrome 上运行良好
  • 对我来说在任何速度下都可以正常工作(OS X 上的 Safari)
  • 我可以“看到”FF3.5 中的问题。关注顶部 2 项,将指针快速移过它们。
  • 在 okw 建议我应该在 animation() 中使用回调函数后我找到了解决方案,谢谢大家

标签: jquery hover mouse out


【解决方案1】:

让我们检查一个违规的操作顺序:

  • 鼠标悬停 - 启动 Ajax 调用
  • 鼠标移出 - 删除兄弟姐妹
  • ajax 成功 - 追加 div。

再加上您没有使用var $this 来声明$this - 因此它是全局的,ajax 调用中的$this 可能会被覆盖。

您可能应该更改您的函数以在 ajax 调用之前创建并附加 &lt;div&gt;,然后稍后附加(添加 cmets):

$(document).ready(function () { 
  //vertical navigation js
  $(".mainnav_v a").hover(function (e) {
    // be sure to SCOPE your $this, so that the other function can't overwrite it
    var $this = $(this)
    $this.stop().animate({  paddingLeft : '16px'}, 300);
    var brand ="";
    var category="designer_frames";
    $this.each(function() {
      var title = this.title;
      if ($this.is('a') && $this.attr('title') != '' && $this.attr('id')==category)
      {  
        brand= this.title;
        // create div BEFORE ajax call, and append it to dom in a hidden state
        var $results = $("<div id='peek_container'/>").hide();
        $this.parent().append($results);
        $.ajax({
          type: "GET",
          url: "xml/peek_menu.xml",
          //ie bug : it send wrong datatype on localmachine
          dataType: ($.browser.msie) ? "text" : "xml",
          success: function(data) {
            var xml;
            if (typeof data == "string") {
              xml = new ActiveXObject("Microsoft.XMLDOM");
              xml.async = false;
              xml.loadXML(data);
            } else {
              xml = data;
            }
            $(category, xml).each(function(){
              $(brand,this).each(function(){
                var title = $(this).attr('title');
                var imgurl = $(this).attr('imgurl');
                var description = $(this).find('description').text();
                var feature1 = $(this).find('feature1').text();
                var feature2 = $(this).find('feature2').text();
                var feature3 = $(this).find('feature3').text();
                var feature4 = $(this).find('feature4').text();

                var html =  '<img src="' + imgurl + '" alt="" /><br /><br /><h1>'+title+'</h1><br />';
                html += '<p>' + description + '</p><br />';
                html += '<ul><li>'+feature1+'</li><li>'+feature2+'</li><li>'+feature3+'</li><li>'+feature4+'</li></ul><br />';
                // set the html of the results object we made.
                $results.show().html(html);
              });
            });
          }
        });
      }
    });
  },
  function (e) {
    var $this = $(this);
    $this.stop().animate({  paddingLeft : '6px'     }, 300);
    $this.siblings().remove();
  });
});

【讨论】:

  • 我可以看到您的想法也有效,但问题已从 okw 的使用回调函数的建议中解决,但我可以看到您的想法也有效,但现在我对回调很满意(时间短)感谢您的回答,稍后会实施
  • 所有使用回调所做的只是让你的问题更加依赖于时间......现在如果你将鼠标从元素上移到另一个元素上,你会遇到同样的问题(而且可能更多) ajax 调用开始和结束之间的一个......
  • @gnarf:我可以看到你方法中的价值。为此+1。这是我对使用回调触发ajax调用的看法。动画序列在鼠标悬停时“停止”,因此在动画完成之前不会触发 ajax 调用。无论动画是否完成,原始案例总是进行 ajax 调用,我认为这是不可取的。因此,我认为这不会是比原始解决方案更糟糕的解决方案。 :)
  • @o.k.w. - 但问题仍然存在,只是在调用链中的 300 毫秒后。想象一下鼠标悬停,动画完成,ajax 启动,mouseout(不删除 div,因为 ajax 调用尚未完成),然后 ajax 完成添加 div(因为我们没有确定 $this 的范围,它会添加到任何 $this设置为,也许是新的鼠标悬停元素,也许是旧的......)那里的各种错误行为......我认为解决核心问题而不是将它们延迟 300 毫秒更可取。
  • 好吧,先生们,我想一切都很好。首先是一个快速修复,然后是一个修复所有的实现。 :)
【解决方案2】:

使用console.log() 或其他一些日志记录方法,您应该能够确定mouseout 是否在mouseover 完成添加内容之前触发,或者是否存在其他问题。

【讨论】:

  • 是的,杰森这样做了,发现它没有触发,然后 o.k.w 好心建议我应该在动画函数中使用回调函数,我试过了,它起作用了
【解决方案3】:

我不是 100% 确定,但我的直觉是,通过 ajax 获取面板的函数调用应该是悬停动画函数的回调。

现在的方式是,悬停动画“独立”于 ajax 调用。

我没有试过这个,所以我可能错了。 :P

【讨论】:

  • 谢谢伙计,这就像魅力一样,为什么我没有想到这个,愚蠢的我,给你自己买杯酒,假装是我的:) gud man the laltian 问候萨尔曼
  • Ermm.. 好的...我现在去买一个。无论如何,很高兴我的“直觉”有帮助:P
猜你喜欢
  • 2013-08-18
  • 2013-07-29
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多