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; }Tengo una barra de navegación y cada uno de estos elementos de la barra de navegación tiene elementos desplegables. Quiero mostrar estos elementos desplegables cuando hago clic en la clase 'desplegable'. Pero el problema es que cuando hago clic en uno de ellos, todos los menús desplegables están visibles. ¿Cómo muestro solo la lista en la que he hecho clic?
Ingrese el siguiente código
<!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>Use el objetivo del evento para obtener el nodo principal, luego use el nodo principal para consultar el elemento oculto ya que todos sus elementos están agrupados en la misma agrupación principal/secundaria. También puede establecer una clase inicial para oculto, display: none; en cada elemento y añádelo al hacer clic. Un bucle forEach establece la visualización de cada elemento en ninguno utilizando la clase oculta al hacer clic.
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>Como se menciona en los comentarios, es mejor usar la técnica de delegación de eventos .
El algoritmo es bastante simple:
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>