简单的 jquery 下拉列表 - clearTimeout、setTimeout 问题 [英] simple jquery dropdown - clearTimeout, setTimeout issues

查看:13
本文介绍了简单的 jquery 下拉列表 - clearTimeout、setTimeout 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

HTML:

    <li><a href="#"><span>一个</span></a></li><li><a href="#"><span>两个</span></a></li><li><li><a href="#"><span>三</span></a></li><ul class="subnav"><li><a href="#">A</a></li><li><a href="#">B</a></li><li><a href="#">C</a></li>

jquery:

var timeout = null;$(document).ready(function() {$("ul.topnav li").mouseover(function() {如果(超时)clearTimeout(超时);$(this).find("ul.subnav").slideDown('fast').show();}).mouseout(function() {timeout = setTimeout(closemenu, 500);});//子菜单鼠标悬停保持下拉菜单打开$("ul.subnav li").mouseover(function() {如果(超时)clearTimeout(超时);}).mouseout(function() {timeout = setTimeout(closemenu, 500);//警报(超时);});//任何点击关闭$(document).click(closemenu);});//关闭所有打开的菜单函数关闭菜单(){$('ul.subnav:visible').hide();如果(超时)clearTimeout(超时);}

我遇到了超时问题.在使用中,如果我将鼠标悬停在三"上,下拉菜单将永远存在.如果我将鼠标悬停在A"上,下拉菜单将永远存在,但如果我将鼠标悬停在B"或更低的位置,菜单将关闭.如果您取消注释//alert(timeout);"它到达那里 B, (和 A) 但超时将有一个值.为什么是这样?我认为 clearTimeout 会使超时变量为空?

解决方案

您可以使用 .hover().data() 像这样:

$(function() {$("ul.topnav li").hover(function() {var timeout = $(this).data("timeout");如果(超时)clearTimeout(超时);$(this).find("ul.subnav").slideDown('fast');}, 功能() {$(this).data("timeout", setTimeout($.proxy(function() {$(this).find("ul.subnav").slideUp();}, 这个), 500));});$(document).click(function() {$('ul.subnav:visible').hide();});});

您可以在此处查看工作演示

不是共享一个全局的timeout变量,而是设置一个超时per顶级

  • ,每个都有一个独立的定时器,当您将鼠标悬停在该元素上时,只会清除 其计时器.另外 .hover() 使用 mouseentermouseleave,而不是 mouseovermouseout,区别在于当你进入一个孩子或者在孩子之间, mouseenter 不会再次触发,并且 mouseleave 不会在我们关心的父
  • 上触发.

    您可以使用上面的演示链接进行测试,我也在第一个菜单中添加了子项,以证明它们是独立的.如果您对那里的 $.proxy 有疑问,它只是让超时匿名函数中的 this 引用我想要的内容(当前的 this)...超时后需要关闭的元素.>

    HTML:

    <ul class="topnav">
        <li><a href="#"><span>One</span></a></li>
        <li><a href="#"><span>Two</span></a></li>
        <li>
            <li><a href="#"><span>Three</span></a></li>
            <ul class="subnav">
                <li><a href="#">A</a></li>
                <li><a href="#">B</a></li>
                <li><a href="#">C</a></li>
            </ul>
        </li>
    </ul>
    

    jquery:

    var timeout = null;
    
    $(document).ready(function() {
    
        $("ul.topnav li").mouseover(function() {
    
            if (timeout) clearTimeout(timeout);
    
            $(this).find("ul.subnav").slideDown('fast').show();
    
        }).mouseout(function() {
            timeout = setTimeout(closemenu, 500);
        });
    
        // sub menu mouseovers keep dropdown open
        $("ul.subnav li").mouseover(function() {
            if (timeout) clearTimeout(timeout);
        }
        ).mouseout(function() {
            timeout = setTimeout(closemenu, 500);
            // alert(timeout);
    
        });
    
        // any click closes
        $(document).click(closemenu);
    });
    
    // Closes all open menus 
    function closemenu() {
        $('ul.subnav:visible').hide();
        if (timeout) clearTimeout(timeout);
    } 
    

    I'm having issues with timeout. In use, if i mouseover "Three", the dropdown stays out forever. if i mouseover "A", dropdown will stay out forever, but if I mouseover "B" or anything lower, the menu will close on me. if you uncomment "// alert(timeout);" it gets there for B, (and A) but timeout will have a value. why is this? i thought clearTimeout would null the timeout variable?

    解决方案

    You can simplify your code overall by using .hover() and .data() like this:

    $(function() {
      $("ul.topnav li").hover(function() {
        var timeout = $(this).data("timeout");
        if(timeout) clearTimeout(timeout);
        $(this).find("ul.subnav").slideDown('fast');
      }, function() {
          $(this).data("timeout", setTimeout($.proxy(function() {
              $(this).find("ul.subnav").slideUp();
          }, this), 500));
      });
      $(document).click(function() {
          $('ul.subnav:visible').hide();
      });
    });​
    

    You can see a working demo here

    Instead of sharing a global timeout variable, this sets a timeout per top level <li>, each one has an independent timer, and when you hover back over that element, only its timer is cleared. Also .hover() uses mouseenter and mouseleave, rather than mouseover and mouseout, the difference is when you go into a child or between children, mouseenter doesn't fire again, and mouseleave doesn't fire on the parent <li> we care about.

    You can test this with the demo link above, I added sub-items to the first menu as well, to demonstrate they're independent. If you happen to have question about the $.proxy in there, it's just making this inside that timeout anonymous function refer to what I want it to (the current this)...the element that needs closing after the timeout.

    这篇关于简单的 jquery 下拉列表 - clearTimeout、setTimeout 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆