我的网站上有一个导航栏。一些导航链接具有与之关联的子菜单。我希望能够将鼠标悬停在具有子菜单并显示子菜单的导航链接上。
但是,我希望子菜单根据窗口大小而有所不同:
如果窗口的宽度大于或等于960px,则我的导航栏为水平。我希望子菜单显示为页面其他内容上方的下拉菜单。
如果窗口的宽度小于960px,则我的导航栏为垂直。我希望子菜单显示为手风琴,向下推其他导航链接。
我也希望脚本在页面加载完成并调整窗口大小时执行。
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()
触发时,上述脚本可以正常工作。
问题出在这里:如果在加载窗口后调整窗口大小,该脚本将创建多个mouseover
和mouseout
事件侦听器。将鼠标悬停在导航链接上会导致子菜单反复上下反弹。
您可以在这里看到我的意思:https://codepen.io/ben393/pen/qLrMmX。
使.hover()
具有($(window).width() >= 960)
的功能
使$(document).ready()
具有$(window).resize()
的功能
有什么想法吗?谢谢!
答案 0 :(得分:1)
正如您提到的,问题在于您每次调整大小时都会继续监听hover
事件。解决此问题的一种简单方法是每次使用以下方法取消绑定相应的DOM事件:
$('.menu-item-has-children').off('mouseenter mouseleave');
请注意,hover()
在后台绑定这两个事件。另请注意,这将删除这些事件的 all 自定义处理程序。您还可以将处理程序函数存储到变量中,如果您想更具体一些,则仅取消绑定它们。
演示(点击“扩展代码段”以全屏对其进行测试):
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>
答案 1 :(得分:0)
将所有内容放到hover()
内,您将获得一个更简单,更逻辑的代码,因为您仅定义一次悬停事件。您还可以依靠toggle类来定义一个与mouseenter
和mouseleave
$(document).ready(function() {
$('.menu-item-has-children').hover(function() {
if ($(window).width() >= 960) {
$(this).children(".sub-menu").toggleClass('show');
} else {
$(this).children(".sub-menu").slideToggle(500);
}
});
});
完整代码:
$(document).ready(function() {
$('.menu-item-has-children').hover(function() {
if ($(window).width() >= 960) {
$(this).children(".sub-menu").toggleClass('show');
} else {
$(this).children(".sub-menu").slideToggle(500);
}
});
});
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.show {
display: block;
}
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>
答案 2 :(得分:0)
如果您将调整大小调用更改为此,那么它将起作用:
$(document).resize(function() {
navMenu();
});
此外,您还应该将所有JS包装在$(document).ready()