代码之家  ›  专栏  ›  技术社区  ›  Sergio

Vanilla javascript切换下拉菜单

  •  2
  • Sergio  · 技术社区  · 7 年前

    我的大脑已经检查过周末了…

    我正在寻找一个简单的javascript解决方案,如果单击另一个主菜单项打开一个下拉菜单框,上一个打开的下拉菜单将关闭,然后显示新单击的主菜单项的下拉菜单。我知道这可能很简单,但我不能想出一个不复杂的解决方案。

    此外,如果单击菜单项外部(文档中不是菜单项或下拉框的任何位置),则应关闭任何打开的下拉框。

    谢谢你的帮助。

    function testFunc(el) {
      var parent = el.parentElement;
      var dd = parent.lastChild.previousSibling;
      dd.classList.toggle('show');
    }
    ul { list-style: none; margin: 0; padding: 0; }
    ul li {
      width: 100px;
      float: left;
      background: #dbdbdb;
      line-height: 2em;
      text-align: center;
      margin: 0 5px;
      cursor: pointer;
    }
    ul li span {
      display: block;
    }
    ul li ul {
      display: none;
    }
    
    .show {
      display: block;
    }
    <ul>
      <li>
        <span onclick="testFunc(this)">Item 1</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span onclick="testFunc(this)">Item 2</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span onclick="testFunc(this)">Item 3</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span onclick="testFunc(this)">Item 4</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
    </ul>
    1 回复  |  直到 7 年前
        1
  •  4
  •   Ivan Jeffrey Zhao    7 年前

    opened null

    let opened = null
    
    function testFunc(el) {
    
      // gets the <ul> element of the clicked menu item
      const menu = el.parentElement.lastChild.previousSibling;
    
      if (!opened) {
    
        // no menu item is shown
        opened = menu
        opened.classList.toggle('show');
    
      } else if (menu == opened) {
    
        // the clicked item is already showing
        menu.classList.toggle('show')
        opened = null
    
      } else {
    
        // the clicked item is hiddden but another one is showing
        opened.classList.toggle('show')
        opened = menu
        opened.classList.toggle('show')
    
      }
    
    }
    

    let opened = null
    
    function testFunc(el) {
    
      const menu =  el.parentElement.lastChild.previousSibling;
      
      if(!opened) {
        opened = menu
        opened.classList.toggle('show');
      } else if(menu == opened) {
        menu.classList.toggle('show')
        opened = null
      } else {
        opened.classList.toggle('show')
        opened = menu
        opened.classList.toggle('show')
      }
      
    }
    ul {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    
    ul li {
      width: 100px;
      float: left;
      background: #dbdbdb;
      line-height: 2em;
      text-align: center;
      margin: 0 5px;
      cursor: pointer;
    }
    
    ul li span {
      display: block;
    }
    
    ul li ul {
      display: none;
    }
    
    .show {
      display: block;
    }
    <ul>
      <li>
        <span onclick="testFunc(this)">Item 1</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span onclick="testFunc(this)">Item 2</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span onclick="testFunc(this)">Item 3</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span onclick="testFunc(this)">Item 4</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
    </ul>

    let opened = null
    const toggleVisibility = e => e.classList.toggle('show')
    
    const toggleDropDown = e => {
    
      const clickedItem = e.target.parentElement.lastChild.previousSibling
    
      toggleVisibility(clickedItem);
    
      if (!opened) {
        opened = clickedItem
      } else if (opened == clickedItem) {
        opened = null
      } else {
        toggleVisibility(opened);
        opened = clickedItem
      }
    
    }
    
    [...document.querySelectorAll('.dropDown')].forEach(dropDown => dropDown.addEventListener('click', toggleDropDown))
    

    let opened = null
    const toggleVisibility = e => e.classList.toggle('show')
    
    const toggleDropDown = e => {
    
      const clickedItem = e.target.parentElement.lastChild.previousSibling
    
      toggleVisibility(clickedItem);
    
      if (!opened) {
        opened = clickedItem
      } else if (opened == clickedItem) {
        opened = null
      } else {
        toggleVisibility(opened);
        opened = clickedItem
      }
    
    }
    
    [...document.querySelectorAll('.dropDown')].forEach(dropDown => dropDown.addEventListener('click', toggleDropDown))
    
    
    
    
    <ul>
      <li>
        <span class="dropDown">Item 1</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span class="dropDown">Item 2</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span class="dropDown">Item 3</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
      <li>
        <span class="dropDown">Item 4</span>
        <ul>
          <li>Sub Item 1</li>
          <li>Sub Item 2</li>
        </ul>
      </li>
    </ul>

    let opened = null
    const toggleVisibility = e => e.classList.toggle('show')
    
    const handleDropdown = e => {
    
      const clickedItem = e.parentElement.lastChild.previousSibling
    
      toggleVisibility(clickedItem)
    
      if (!opened) {
        opened = clickedItem
      } else if (opened == clickedItem) {
        opened = null
      } else {
        toggleVisibility(opened)
        opened = clickedItem
      }
    
    }
    
    const handleClick = e => {
    
      if (e.target.className.includes('dropDown')) {
        handleDropdown(e.target)
      } else if (opened) {
        toggleVisibility(opened)
        opened = null
      }
    
    }
    
    document.addEventListener('click', handleClick)
    

    let opened = null
    const toggleVisibility = e => e.classList.toggle('show')
    
    const handleDropdown = e => {
    
      const clickedItem = e.parentElement.lastChild.previousSibling
    
      toggleVisibility(clickedItem)
    
      if (!opened) {
        opened = clickedItem
      } else if (opened == clickedItem) {
        opened = null
      } else {
        toggleVisibility(opened)
        opened = clickedItem
      }
    
    }
    
    const handleClick = e => {
    
      if (e.target.className.includes('dropDown')) {
        handleDropdown(e.target)
      } else if (opened) {
        toggleVisibility(opened)
        opened = null
      }
    
    }
    
    document.addEventListener('click', handleClick)
    
    
    
    
    <