jQuery的.hover()和$(window).resize()出现奇怪的行为

4

我想做什么:

我的网站上有一个导航栏。一些导航链接有与之相关联的子菜单。我希望能够将鼠标悬停在具有子菜单的导航链接上,然后让子菜单出现。

但是,我希望子菜单根据窗口大小的不同而以不同的方式出现:

  • 如果窗口宽度大于等于960像素,则我的导航栏是水平的。我希望子菜单作为下拉菜单出现在页面上方的其他内容之上。

  • 如果窗口宽度小于960像素,则我的导航栏是垂直的。我希望子菜单作为手风琴式菜单出现,将其他导航链接向下推。

我还希望我的脚本在页面加载完成和调整窗口大小时执行。

我的脚本:

function navMenu() {
  if ($(window).width() >= 960) {
    $('.menu-item-has-children').hover(function() {
      $(this).children(".sub-menu").css('display', 'block');
    }, function() {
      $(this).children(".sub-menu").css('display', 'none');
    });
  } else {
    $('.menu-item-has-children').hover(function() {
        $(this).children(".sub-menu").slideToggle(500);
      }, function() {
        $(this).children(".sub-menu").slideUp(500);
    });
  }
}
$(document).ready(function() {
   navMenu();
});
$(window).resize(function() {
   navMenu();
});

发生了什么:

$(document).ready()被触发时,上述脚本可以正常工作。

问题在于:如果我在加载完页面后调整窗口大小,该脚本会创建多个mouseovermouseout事件监听器。悬停在导航链接上会导致子菜单反复弹跳。

您可以在此处查看我的意思:https://codepen.io/ben393/pen/qLrMmX

我尝试过的一些方法(目前还没有奏效):

  • .hover()作为($(window).width() >= 960)的一个函数

  • $(document).ready()作为$(window).resize()的一个函数

有什么想法吗?谢谢!

2个回答

1

如您所提,问题在于您在每次调整大小时都会持续监听hover事件。解决这个问题的简单方法是每次取消绑定相应的DOM事件,使用以下代码:

$('.menu-item-has-children').off('mouseenter mouseleave');

请注意,hover()在后台绑定这两个事件。还要注意,这将删除所有这些事件的自定义处理程序。您也可以将处理程序函数存储到变量中,并仅取消绑定它们,如果您想更具体地进行操作。
演示(单击“展开片段”以在全屏幕上测试):

function navMenu() {
  $('.menu-item-has-children').off('mouseenter mouseleave');
  if ($(window).width() >= 960) {
    $('.menu-item-has-children').hover(function() {
      $(this).children(".sub-menu").css('display', 'block');
    }, function() {
      $(this).children(".sub-menu").css('display', 'none');
    });
  } else {
    $('.menu-item-has-children').hover(function() {
      $(this).children(".sub-menu").slideToggle(500);
    }, function() {
      $(this).children(".sub-menu").slideUp(500);
    });
  }
}
$(document).ready(function() {
  navMenu();
});
$(window).resize(function() {
  navMenu();
});
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  font-weight: bold;
}

ul li {
  display: inline-block;
  padding: 10px;
  background-color: grey;
}

ul.sub-menu {
  display: none;
  font-weight: normal;
  position: absolute;
}

ul.sub-menu li {
  display: block;
}

@media only screen and (max-width: 959px) {
  ul li {
    display: block;
    width: 100px;
  }
  ul.sub-menu {
    position: relative;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="main_header_menu">
  <li class="menu-item-has-children">Main item 1
    <ul class="sub-menu">
      <li>sub item 1</li>
      <li>sub item 2</li>
      <li>sub item 3</li>
    </ul>
  </li>
  <li>Main item 2</li>
  <li class="menu-item-has-children">Main item 3
    <ul class="sub-menu">
      <li>sub item 1</li>
      <li>sub item 2</li>
      <li>sub item 3</li>
    </ul>
  </li>
</ul>


完美运行。谢谢@Jeto! - Ben393

0
如果你将调整大小调用更改为以下形式,则它可以工作:
``` $(document).resize(function() { navMenu(); }); ```
此外,你应该将所有JS代码都包装在 $(document).ready()中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接