Quiero hacer un botón que pueda abrir una ventana cuando se hace clic en el botón ~
Pero cuando aparezca la ventana, haga clic en el menú verde, el menú no desaparecerá, ¡solo haga clic nuevamente o en cualquier espacio en blanco alrededor del menú! los
el menú se cerrará de nuevo, pero yo escribí un juicio ¿por qué no se puede realizar esta función? Espero contar con su ayuda, gracias.
const el = document.querySelector('.click') const menu = document.querySelector('.menu'); el.onclick = function() { menu.classList.toggle("showmenu"); } window.onclick = function(e) { if (!e.classList.contains('menu') || !e.classList.contains('menu_item')) { menu.removeClass('showmenu'); } }
.click { background-color: yellow; padding: 20px; } .menu { display: inline-block; background-color: green; list-style-type: none; display: none; } .menu a { text-decoration: none; color: #fff; padding: 30px; font-size: 20px; } .showmenu { display: inline-block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <button type="button" class="click">click</button> <ul class="menu"> <li class="menu_item"><a href="#">item1</a></li> <li class="menu_item"><a href="#">item2</a></li> <li class="menu_item"><a href="#">item3</a></li> </ul>
Pocos problemas:
Su detector de eventos de click
global está tratando de obtener la propiedad classList
del evento, que no existe. En su lugar, debería obtener el destino del evento, que se recupera a través de la propiedad de target
.
No hay un método removeClass
. Utilice classList.remove
en su lugar.
Llame a Event.stopPropagation
en el detector de eventos de click
vinculado a .click
, de modo que el detector de eventos de click
global no maneje el evento (de lo contrario, cerrará el menú inmediatamente después de abrirlo).
const el = document.querySelector('.click') const menu = document.querySelector('.menu'); el.onclick = function(e) { menu.classList.toggle("showmenu"); e.stopPropagation(); } window.onclick = function(e) { if (!menu.contains(e.target)) { menu.classList.remove('showmenu'); } }
.click { background-color: yellow; padding: 20px; } .menu { display: inline-block; background-color: green; list-style-type: none; display: none; } .menu a { text-decoration: none; color: #fff; padding: 30px; font-size: 20px; } .showmenu { display: inline-block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <button type="button" class="click">click</button> <ul class="menu"> <li class="menu_item"><a href="#">item1</a></li> <li class="menu_item"><a href="#">item2</a></li> <li class="menu_item"><a href="#">item3</a></li> </ul>
El método jQuery .removeClass()
se usó en un objeto JavaScript simple (es decir menu
). En el ejemplo, se .classList.remove()
en su lugar. Si desea usar .removeClass()
en su lugar, debe convertir menu
en un objeto jQuery const menu = $('.menu')
entonces menu.removeClass('showmenu')
funcionará.
Además, cambié un poco el CSS para evitar que el botón salte y domar esos enlaces: se desvanecían de los bordes percibidos del menú. El CSS, por supuesto, no es un requisito de solución.
Solución
Convierta todos los controladores de eventos en un solo controlador de eventos y delegue el comportamiento con declaraciones de flujo de control , propiedad Event.target
y método .matches()
. A continuación se utiliza el paradigma de programación denominado delegación de eventos .
const btn = document.querySelector('.click') document.body.onclick = popUp; function popUp(e) { const clicked = e.target; const menu = document.querySelector('.menu'); if (clicked.matches('.click')) { menu.classList.toggle("showmenu"); } else if (!clicked.matches('.click') && !clicked.matches('.menu')) { menu.classList.remove('showmenu'); } else return false; }
body { display: flex; justify-content: flex-start; align-items: flex-start; } .click { background-color: yellow; padding: 20px; } .menu { display: none; background-color: green; list-style-type: none; } .menu a { display: block; text-decoration: none; color: #fff; padding: 5px; font-size: 20px; } .showmenu { display: inline-block; }
<button type="button" class="click">click</button> <ul class="menu"> <li class="menu_item"><a href="/#">item1</a></li> <li class="menu_item"><a href="/#">item2</a></li> <li class="menu_item"><a href="/#">item3</a></li> </ul> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>