单击时如何显示下拉菜单

How to show dropdown menu when clicked

js

const navItems = document.querySelectorAll('.navbar__items')
const dropDown = document.querySelectorAll('.dropdown')

dropDown.forEach(element => {
 element.addEventListener('click',()=>{
     {
         navItems.forEach(nav =>{
             nav.classList.toggle('drop')
         })
     }
         
 })
})

HTML

   <ul class="navbar">
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
</ul>

CSS

   .navbar{
  position: relative;
}

.navbar__items{
  position: absolute;
  display: none;
}

.drop{ 
  display: block;
}

我有一个导航栏,每个导航栏项目都有下拉项目。我想在单击 'dropdown' class 时显示这些下拉项。但问题是当我单击其中一个时,所有下拉菜单都可见。如何只显示我点击过的列表?

输入以下代码

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.dropbtn {
  background-color: #3498DB;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}

.dropbtn:hover, .dropbtn:focus {
  background-color: #2980B9;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  overflow: auto;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropdown a:hover {background-color: #ddd;}

.show {display: block;}
</style>
</head>
<body>



<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">Click</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#home">Clicked</a>
    <a href="#about">Clicked</a>
    <a href="#contact">Clicked</a>
  </div>
</div>

<script>
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {
    var dropdowns = document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}
</script>

</body>
</html>

使用事件目标获取 parentNode,然后使用 parentNode 查询隐藏元素,因为所有元素都分组在同一个 parent/child 分组中。您还可以为隐藏设置初始 class,在每个元素中设置 display: none; 并在单击时添加它。 forEach 循环使用隐藏的 class 将每个元素显示为 none。

const navItems = document.querySelectorAll('.navbar__items')
const dropDown =  document.querySelectorAll('.dropdown') 

// callback function that passes in the event => e from your listener
function showDropdown (e){
  // set each navbar__items element display: none using hidden class
  navItems.forEach(el => el.classList.add('hidden'))
  // query the specific .navbar__items in the event.targets group 
  let dd = e.target.parentNode.querySelector('.navbar__items') 
  // remove the hidden class a nd show the dropdown for this event.target
  dd.classList.remove('hidden')  
}

// iterate over the dropdown element 
dropDown.forEach(element => {
  // function showDropdown on click
  element.addEventListener('click', showDropdown)
})
.navbar {
  position: relative;
}

.navbar__items {
  position: absolute;
  left: 75px;
}

.hidden {  
  display: none;
}
<ul class="navbar">
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items hidden">
      <li><a href="#">clicked 1</a></li>
      <li><a href="#">clicked 1</a></li>
      <li><a href="#">clicked 1</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items hidden">
      <li><a href="#">clicked 2</a></li>
      <li><a href="#">clicked 2</a></li>
      <li><a href="#">clicked 2</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items hidden">
      <li><a href="#">clicked 3</a></li>
      <li><a href="#">clicked 3</a></li>
      <li><a href="#">clicked 3</a></li>
    </ul>
  </li>
</ul>

如评论中所述,最好使用 Event Delegation 技术。

算法很简单:

  1. 在父元素上添加监听器
  2. 点击时检查下拉菜单是否被点击
  3. 获取我需要打开的下拉菜单
  4. 关闭其他下拉菜单
  5. 打开 3 的下拉菜单。

const allDropdowns = document.querySelectorAll('.navbar__items')
const DROP_CLASS = 'drop';
const navbar = document.querySelector('.navbar');


navbar.addEventListener('click', ({target}) => {
    if (!target.classList.contains('dropdown')) return;
  
  const parent = target.parentNode;
  const navItems = parent
    .querySelector('.navbar__items');

  allDropdowns.forEach(el => el !== navItems && el.classList.remove(DROP_CLASS));
  
  if (navItems) {
    navItems.classList.toggle(DROP_CLASS);  
  }
});
.navbar{
  position: relative;
}

.navbar__items{
  position: absolute;
  left: 80px;
  display: none;
}

.drop{ 
  display: block;
}
   <ul class="navbar">
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  <li class="nav-menu">
    <div class="dropdown">click</div>
    <ul class="navbar__items">
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
      <li><a href="#">clicked</a></li>
    </ul>
  </li>
  </ul>

您应该将 html 中的 onclick 方法添加到每个具有相同方法名称的下拉列表,而不是使用 addEventlistener,但更改每个下拉列表的 ul class 名称,然后传递 class name 在方法中,然后使用参数 class name.

切换下拉列表

例如,

 function onClick(item) {
    if (document.getElementsByClassName(item).classList.contains('hidden')) {
        document.getElementsByClassName('dropdown').classList.remove('hidden');
    }
    if (!document.getElementsByClassName(item)[0].classList.contains('hidden')) {
        document.getElementsByClassName('dropdown').classList.add('hidden');
    }
}
<ul class="navbar">
    <li class="nav-menu">
        <div class="dropdown" onclick="onClick('navbar_items1')">click</div>
        <ul class="navbar__items1 hidden">
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
        </ul>
    </li>
    <li class="nav-menu">
        <div class="dropdown" onclick="onClick('navbar_items2')">click</div>
        <ul class="navbar__items2 hidden">
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
        </ul>
    </li>
    <li class="nav-menu">
        <div class="dropdown" onclick="onClick('navbar_items3')">click</div>
        <ul class="navbar__items3 hidden">
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
            <li><a href="#">clicked</a></li>
        </ul>
    </li>
</ul>