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

时间:2019-09-10 08:14:40

标签: javascript html css

我一直在学习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;
}

``

4 个答案:

答案 0 :(得分:0)

我认为这是可能发生的,因为起初您要添加nav-open类,而不是检查是否存在,如果是,则向窗口添加事件(窗口仍然可以捕获此事件)并删除该类,因此不应执行任何操作发生。尝试在event.stopPropagation()

下添加event.preventDefault()
(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');
          }
        };
      };
    });
  });


})();```

答案 1 :(得分:0)

考虑使用事件委托。单击页面上的任何位置时,请运行事件侦听器。如果单击的目标不在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>

答案 2 :(得分:0)

也许是这样,代码应该具有自我解释性

// 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>

答案 3 :(得分:0)

这是一个糟糕的演示

(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');

这将始终是第一个子菜单,因此我将其删除。 如果要获取每个元素的subMenu,则应执行以下操作:

btn.querySelector('.sub-menu')

现在,它将为您已经完成的forEach中的每个元素提供子菜单。


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

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