在jQuery中创建向下滑动子菜单的最有效方法

Most efficient way to create a slide-down submenu in jQuery

本文关键字:菜单 方法 有效 jQuery 创建      更新时间:2023-09-26

我正在尝试制作一个子菜单,当鼠标悬停在某个元素上时,该子菜单会从主菜单栏向下滑动。我目前正在使用以下代码进行此操作:

$(document).ready( function() {
  $('.navlist li a').hover( function() {
    if( $(this).attr( 'data-param' ) == "parent" )
    {
      $('#subnavbar-' + $(this).attr( 'data-slug' )).slideDown( 200 );
    }
  }, function() {
    if( $(this).attr( 'data-param' ) == "parent" )
    {
      var name = '#subnavbar-' + $(this).attr( 'data-slug' );
      setTimeout( function() {
        if( !$(name).is(':hover') )
        {
          $(name).slideUp( 200 );
        }
      }, 200 );
    }
  });
});
a {
  color: white;
}
.navbar {
  background-color: green;
  margin-bottom: 0;
  height: 30px;
}
ul.navlist {
  list-style: none;
  text-indent: 0;
  margin: 0;
  padding: 0;
  float: left;
}
ul.navlist li {
  display: block;
  width: 100px;
  float: left;
}
.subnavbar {
  background-color: blue;
  margin-top: 0;
  height: 20px;
  display: none;
}
ul.subnavlist {
  list-style: none;
  text-indent: 0;
  margin: 0;
  padding: 0;
  float: left;
}
ul.subnavlist li {
  display: block;
  width: 80px;
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar">
  <ul class="navlist">
    <li><a href="#">Item 1</a></li>
    <li><a href="#" data-param="parent" data-slug="test">Hover Here</a></li>
    <li><a href="#">Item 3</a></li>
  </ul>
</div>
<div class="subnavbar" id="subnavbar-test">
  <ul class="subnavlist">
    <li><a href="#">Subitem 1</a></li>
    <li><a href="#">Subitem 2</a></li>
    <li><a href="#">Subitem 3</a></li>
  </ul>
</div>

正如您通过运行代码片段所看到的;它是有效的,但有很多错误,我不确定解决的最佳方法是什么。首先,如果用户在主菜单项上来回悬停,我不希望事件被垃圾邮件发送,我可以使用setTimeout()clearTimeout()来解决这个问题,但如果可能的话,我希望有更好的方法。其次,我不确定如果用户悬停在子菜单栏而不是父菜单项上,如何最好地使其不收回,我目前是如何做到的,但如果用户悬停离开,导航栏就不会收回。

有效的解决方案是只使用CSS。绝对不需要JQUERY!试试这个Fiddle。

HTML:

<nav>
    <ul>
        <li><a href="#">Item 1</a></li>
        <li><a href="#">Item 2</a>
            <ul>
                <li><a href="#">Sub Item 1</a></li>
                <li><a href="#">Sub Item 2</a></li>
                <li><a href="#">Sub Item 3</a>
                    <ul>
                        <li><a href="#">Sub Sub Item 1</a></li>
                        <li><a href="#">Sub Sub Item 2</a></li>
                    </ul>
                </li>
            </ul>
        </li>
        <li><a href="#">Item 3</a>
            <ul>
                <li><a href="#">Sub Item 1</a></li>
                <li><a href="#">Sub Item 2</a></li>
            </ul>
        </li>
    </ul>
</nav>

CSS代码:

nav {
    margin: 100px auto;
    text-align: center;
}
nav ul ul {
    display: none;
}
nav ul li:hover > ul {
    display: block;
}
nav ul {
    background: -moz-linear-gradient(center top , #efefef 0%, #bbbbbb 100%) repeat scroll 0 0 rgba(0, 0, 0, 0);
    border-radius: 10px;
    box-shadow: 0 0 9px rgba(0, 0, 0, 0.15);
    display: inline-table;
    list-style: outside none none;
    padding: 0 10px;
    position: relative;
}
nav ul::after {
    clear: both;
    content: "";
    display: block;
}
nav ul li {
    float: left;
}
nav ul li:hover {
    background: -moz-linear-gradient(center top , #4f5964 0%, #5f6975 40%) repeat scroll 0 0 rgba(0, 0, 0, 0);
}
nav ul li:hover a {
    color: #fff;
}
nav ul li a {
    color: #757575;
    display: block;
    padding: 15px 20px;
    text-decoration: none;
}
nav ul ul {
    background: none repeat scroll 0 0 #5f6975;
    border-radius: 0;
    padding: 0;
    position: absolute;
    top: 100%;
}
nav ul ul li {
    border-bottom: 1px solid #575f6a;
    border-top: 1px solid #6b727c;
    float: none;
    position: relative;
}
nav ul ul li a {
    color: #fff;
    padding: 5px 10px;
}
nav ul ul li a:hover {
    background: none repeat scroll 0 0 #4b545f;
}
nav ul ul ul {
    left: 100%;
    position: absolute;
    top: 0;
}

正如你告诉我更好的css一样,我为你做了一个快速的小提琴

当然,你需要打磨风格,但"工作"是存在的。

css只是:

    .container {
    height:30px;
    background-color:green;
    color:#fff;
}
.container > ul {position:relative;}
.container > ul li {
    display:inline-block;
    margin-right:30px;
}
.container > ul >li > ul {
    position:absolute;
    left:0;
    background-color:blue;
    top:0px;
    z-index:-1;       
}
.container > ul > li:hover > ul {
    top:30px;
    -webkit-transition: all 0.4s ease;
    -moz-transition: all 0.4s ease;
    -ms-transition: all 0.4s ease;
    -o-transition: all 0.4s ease;
    transition: all 0.4s ease;
}

编辑:我更改了使用顶部高度进行过渡的方式和方向。查看

要解决您的第一个问题,我建议使用jQuery插件Hover Intent。顾名思义,这提供了一种简单的方法来确定用户是否打算悬停在元素上,并通过多次快速悬停在元素内外来避免垃圾邮件的可能性。

为了解决第二个问题,如果可能的话,您可以在navbar和sub-vbar周围添加一个包含元素,并在离开包含元素时使用它来关闭sub-vbar,如果sub-vbar恰好可见的话。

HTML:

<div id="containing_element">
   <div class="navbar">
      <ul class="navlist">
         <li><a href="#">Item 1</a></li>
         <li><a href="#" id="hoverlink">Hover Here</a></li>
         <li><a href="#">Item 3</a></li>
      </ul>
   </div>
   <div class="subnavbar" id="subnavbar-test">
      <ul class="subnavlist">
         <li><a href="#">Subitem 1</a></li>
         <li><a href="#">Subitem 2</a></li>
         <li><a href="#">Subitem 3</a></li>
      </ul>
   </div>
</div>

jQuery:

$(document).ready( function() {
    function hoverEnter() {
        $('#subnavbar-test').slideDown(200);
    }
    $('#hoverlink').hoverIntent( hoverEnter );
    $('#containing_element').mouseleave(function () {
        if($('#subnavbar-test').is(':visible')) {
            $('#subnavbar-test').slideUp(200);
        }               
    });
});

记住还要包含悬停意图的脚本。