有人可以告诉我我的下拉菜单javascript代码出了什么问题吗



我一直在学习Javascript,作为一些练习,我想我会为自己创建一个下拉导航菜单,它适用于"点击"而不是悬停。我已经创建了下面的代码(不起作用(,我想知道是否有人可以解释为什么,以便我可以看到我出错的地方。

我可以打开下拉菜单,但是当我添加代码以关闭下拉菜单时,下拉菜单甚至没有打开。

我希望有人能指出我正确的方向,这样我就能看到我哪里出了问题,我可以避免将来出现此类问题

(function() {
let menuHeader = document.querySelectorAll('.menu-item-has-children');
let subMenu = document.querySelector('.sub-menu');
menuHeader.forEach(function(btn) {
btn.addEventListener('click', function(event) {
event.preventDefault();
subMenu.classList.add('nav-open');
// Close if anywhere on screen aprt form menu is clicked
if (subMenu.classList.contains('nav-open')) {
window.onclick = function(event) {
if (!event.target.classList.contains('sub-menu')) {
subMenu.classList.remove('nav-open');
}
};
};
});
});
})();
<nav class="main-nav">
<ul>
<li><a href="" title="Home">Home</a></li>
<li class="menu-item-has-children"><a href="#" title="What We Do">What We Do</a>
<ul class="sub-menu">
<li><a href="" title="">Page 1</a></li>
<li><a href="" title="">Page 2</a></li>
<li><a href="" title="">Page 3</a></li>
<li><a href="" title="">Page 4</a></li>
<li><a href="" title=" ">Page 5</a></li>
<li><a href="" title="">Page 6</a></li>
</ul>
</li>
<li class="menu-item-has-children"><a href="#" title="Our Work">Our Work</a>
<ul class="sub-menu">
<li><a href="" title="">Portfolio 1</a></li>
<li><a href="" title="">Portfolio 2</a></li>
<li><a href="" title="">Portfolio 3</a></li>
<li><a href="" title="">Portfolio 4</a></li>
<li><a href="" title="">Portfolio 5</a></li>
</ul>
</li>
<li><a href="" title="">Contact</a></li>
</ul>
</nav>

根据要求,CSS 如下

.main-nav ul > li   {
display: inline;
position: relative;
}

.main-nav ul li  a  {
display: inline-block;
font-family: bebas-neue, sans-serif;
font-style: normal;
font-weight: 400;
text-decoration: none;
color: #333;
font-size: 1.3em;
padding: 0.5em 0.8em 0.8em 0.8em;
transition: background 0.2s linear;
}
.main-nav ul li  a:hover    {
background: #00a492;
color: #fff;
}
.main-nav ul li a:not(:only-child):after {
content: '25bc';
font-size: 0.6em;
position: relative;
top: -4px;
left: 2px;
}

/* Second Level of Navigation */
.main-nav ul li  ul {
width: 250px;
position: absolute;
top: 160%;
left: 0;
background: #00a492;
}
.main-nav ul li  ul li a    {
display: block;
}
.sub-menu   {
display: none;
}
.nav-open   {
display: block;
}
.slicknav_menu {
display:none;
}
.highlight-btn  {
background: #00a492 !important;
color: #fff !important;
}

''

请考虑改用事件委派。单击页面上的任意位置时,运行事件侦听器。如果单击的目标不在 LI 内,请使用.nav-open从现有元素中删除.nav-open(如果有(。否则,如果单击的目标是<a>(外部.menu-item-has-children的后代(,则导航到其第二个子项 (.children[1]( 并向其中添加类:

function closeOpenNav() {
const currentOpen = document.querySelector('.nav-open');
if (currentOpen) {
currentOpen.classList.remove('nav-open');
}
}
window.addEventListener('click', (event) => {
const li = event.target.closest('.menu-item-has-children');
if (!li) {
// Close if anywhere on screen aprt form menu is clicked
console.log('closing');
closeOpenNav();
return;
}
if (event.target.parentElement !== li) {
// The clicked element is a descendant of a `.nav-open`
// so, don't do anything
return;
}
event.preventDefault();
closeOpenNav();
const thisSubMenu = li.children[1];
thisSubMenu.classList.add('nav-open');
});
.sub-menu {
display: none;
}
.nav-open {
display: block;
}
<nav class="main-nav">
<ul>
<li><a href="" title="Home">Home</a></li>
<li class="menu-item-has-children"><a href="#" title="What We Do">What We Do</a>
<ul class="sub-menu">
<li><a href="" title="">Page 1</a></li>
<li><a href="" title="">Page 2</a></li>
<li><a href="" title="">Page 3</a></li>
<li><a href="" title="">Page 4</a></li>
<li><a href="" title=" ">Page 5</a></li>
<li><a href="" title="">Page 6</a></li>
</ul>
</li>
<li class="menu-item-has-children"><a href="#" title="Our Work">Our Work</a>
<ul class="sub-menu">
<li><a href="" title="">Portfolio 1</a></li>
<li><a href="" title="">Portfolio 2</a></li>
<li><a href="" title="">Portfolio 3</a></li>
<li><a href="" title="">Portfolio 4</a></li>
<li><a href="" title="">Portfolio 5</a></li>
</ul>
</li>
<li><a href="" title="">Contact</a></li>
</ul>
</nav>

我认为这可能会发生,因为首先您正在添加nav-open类,而不是检查它是否存在,如果是,您将事件添加到窗口(窗口仍然可以捕获此事件(并删除此类,因此什么都不会发生。尝试在event.preventDefault()下添加event.stopPropagation()

(function() {
let menuHeader = document.querySelectorAll('.menu-item-has-children');
let subMenu = document.querySelector('.sub-menu');
menuHeader.forEach(function(btn) {
btn.addEventListener('click', function(event) {
event.preventDefault();
event.stopPropagation()
subMenu.classList.add('nav-open');
// Close if anywhere on screen aprt form menu is clicked
if (subMenu.classList.contains('nav-open')) {
window.onclick = function(event) {
if (!event.target.classList.contains('sub-menu')) {
subMenu.classList.remove('nav-open');
}
};
};
});
});

})();```

这是一个工作演示

(function() {
let menuHeader = document.querySelectorAll('.menu-item-has-children');
let subMenus = document.querySelectorAll('.sub-menu');
menuHeader.forEach(function(btn) {
btn.querySelector('a').addEventListener('click', function(event) {
event.preventDefault();
			event.stopImmediatePropagation();
closeAllMenus();
btn.querySelector('.sub-menu').classList.add('nav-open');
});
});
document.addEventListener("click", function(){
	closeAllMenus();
});

function closeAllMenus(){
	subMenus.forEach(function(ele) {
	ele.classList.remove('nav-open');
});
}
})();
.sub-menu{
display: none;
}
.sub-menu.nav-open{
display: block;
}
<nav class="main-nav">
<ul>
<li><a href="" title="Home">Home</a></li>
<li class="menu-item-has-children">
<a href="#" title="What We Do">What We Do</a>
<ul class="sub-menu">
<li><a href="" title="">Page 1</a></li>
<li><a href="" title="">Page 2</a></li>
<li><a href="" title="">Page 3</a></li>
<li><a href="" title="">Page 4</a></li>
<li><a href="" title=" ">Page 5</a></li>
<li><a href="" title="">Page 6</a></li>
</ul>
</li>
<li class="menu-item-has-children"><a href="#" title="Our Work">Our Work</a>
<ul class="sub-menu">
<li><a href="" title="">Portfolio 1</a></li>
<li><a href="" title="">Portfolio 2</a></li>
<li><a href="" title="">Portfolio 3</a></li>
<li><a href="" title="">Portfolio 4</a></li>
<li><a href="" title="">Portfolio 5</a></li>
</ul>
</li>
<li><a href="" title="">Contact</a></li>
</ul>
</nav>

代码上的第一个错误是声明了这一点

let subMenu = document.querySelector('.sub-menu');

这始终是第一个子菜单,所以我只是删除了它。 如果你想获取每个元素的子菜单,你应该做这样的事情:

btn.querySelector('.sub-menu')

所以现在它将获取您已经做的 forEach 中每个元素的子菜单。


要关闭文档单击上的菜单,我刚刚在文档单击时制作了一个事件侦听器,它将从任何子菜单中删除类nav-open

document.addEventListener("click", function(){
subMenus.forEach(function(ele) {
ele.classList.remove('nav-open');
});
});

也许是这样,代码应该是不言自明

// Dropdown Menu
(function(){
let menuHeader = document.querySelectorAll('.menu-item-has-children');
menuHeader.forEach(function(btn){
btn.addEventListener('click', function(event){
event.preventDefault();

if(this.classList.contains('nav-open')) {
return this.classList.remove('nav-open');
}

var openNavPoints = document.querySelectorAll('.menu-item-has-children.nav-open');
if(openNavPoints.length >= 1) {
[...openNavPoints].forEach(function(openNavPoint) {
openNavPoint.classList.remove('nav-open');
});
}
this.classList.add('nav-open');

});
});
})();
.menu-item-has-children .sub-menu {
display: none;
}
.menu-item-has-children.nav-open .sub-menu {
display: block;
}
<nav class="main-nav">
<ul>
<li><a href="" title="Home">Home</a></li>
<li class="menu-item-has-children"><a href="#" title="What We Do">What We Do</a>
<ul class="sub-menu">
<li><a href="" title="">Page 1</a></li>
<li><a href="" title="">Page 2</a></li>
<li><a href="" title="">Page 3</a></li>
<li><a href="" title="">Page 4</a></li>
<li><a href="" title=" ">Page 5</a></li>
<li><a href="" title="">Page 6</a></li>
</ul></li>
<li class="menu-item-has-children"><a href="#" title="Our Work">Our Work</a>
<ul  class="sub-menu">
<li><a href="" title="">Portfolio 1</a></li>
<li><a href="" title="">Portfolio 2</a></li>
<li><a href="" title="">Portfolio 3</a></li>
<li><a href="" title="">Portfolio 4</a></li>
<li><a href="" title="">Portfolio 5</a></li>
</ul>
</li>
<li><a href="" title="">Contact</a></li>
</ul>
</nav>

最新更新