繁体   English   中英

如何使下拉菜单正确打开?

[英]How to make drop down menus open properly?

我在一个页面上有 29 个可点击的下拉菜单。 我需要它们在点击时打开,然后在点击另一个或页面上的任何其他地方时关闭。 我从 w3schools.com 得到了这个代码。

现在此代码将打开页面上的第一个菜单。 但是,当我单击另一个菜单时,它只会再次打开第一个菜单。 我无法打开页面上的任何其他菜单。 无论单击什么,唯一会打开的菜单是第一个菜单。

我玩弄代码并最终能够打开其他菜单,问题是第一个菜单将保持打开状态。 例如,我会单击菜单 1 并打开它。 当我单击菜单 2 时,它会打开,但菜单 1 也会保持打开状态。 这是页面上的每个菜单。

我弄乱了代码,以至于菜单不再起作用,我不得不求助于我开始使用的代码。

 /* When the user clicks on the button, toggle between hiding and showing the dropdown content */ function myFunction() { document.getElementById("myDropdown").classList.toggle("show"); } // Close the dropdown menu if the user clicks outside of it 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'); } } } }
 /* Dropdown Button */ .dropbtn { background-color: #3498DB; color: white; padding: 16px; font-size: 16px; border: none; cursor: pointer; } /* Dropdown button on hover & focus */ .dropbtn:hover, .dropbtn:focus { background-color: #2980B9; } /* The container <div> - needed to position the dropdown content */ .dropdown { position: relative; display: inline-block; } /* Dropdown Content (Hidden by Default) */ .dropdown-content { display: none; position: absolute; background-color: #f1f1f1; min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; } /* Links inside the dropdown */ .dropdown-content a { color: black; padding: 12px 16px; text-decoration: none; display: block; } /* Change color of dropdown links on hover */ .dropdown-content a:hover {background-color: #ddd} /* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */ .show {display:block;}
 <div class="dropdown"> <button onclick="myFunction()" class="dropbtn">Dropdown</button> <div id="myDropdown" class="dropdown-content"> <a href="#">Link 1</a> <a href="#">Link 2</a> <a href="#">Link 3</a> </div> </div>

我需要的是每个菜单都能被点击。 然后,当我点击页面或其他菜单时,第一个菜单将关闭并打开第二个菜单。 一次只打开一个菜单。

谢谢!

首先,尽可能远离W3Schools,因为众所周知,它已经过时,不完整或者说是错误的信息。 因此,代码中的许多技术都已过时,不应使用,例如onXyz 内联事件属性 ,JavaScript事件属性和getElementsByClassName()的使用。 众所周知, Mozilla Developer's Network是一个权威资源。

这里的整体解决方案是使用事件委托并允许事件从其原始元素( 事件目标冒泡到处理它们的document 这允许我们为每个菜单创建一个事件处理程序而不是一个。 然后,无论单击哪个菜单,事件处理函数都会将它们全部折叠,然后只展开所单击的菜单。

请注意,在以下代码中,HTML中没有JavaScript,没有元素具有id属性,并且菜单默认应用了一个CSS类hide ,而不是在元素CSS类中设置display:none 这允许我们自己删除该类,使其余的CSS保持不变。

不依赖于id ,所以当你添加另一个下拉结构时,它只会工作而不需要改变所需的JavaScript。

 // Get all the menus into an array, just once: let menus = Array.prototype.slice.call(document.querySelectorAll(".dropdown-content")); let openMenu = null; /* When the user clicks on the button, toggle between hiding and showing the dropdown content */ function hideAllMenus() { // Get all the dropdowns into an array. menus.forEach(function(dropdown) { // If the element currently is not hidden if(!dropdown.classList.contains("hide")){ openMenu = dropdown; dropdown.classList.add('hide'); // Hide it } }); } // Close the dropdown menu if the user clicks outside of it document.addEventListener("click", function(event) { hideAllMenus(); // Hide all the menus // If the clicked item was a menu if (event.target.classList.contains('dropbtn')) { if(event.target.nextElementSibling === openMenu){ event.target.nextElementSibling.classList.add("hide"); openMenu = null; } else { // Go to the next element that is a sibling of the one that got clicked (the menu) // and toggle the use of the `hide` CSS class event.target.nextElementSibling.classList.remove("hide"); // Show the one that was clicked openMenu = event.target.nextElementSibling; } } }); 
 /* Dropdown Button */ .dropbtn { background-color: #3498DB; color: white; padding: 16px; font-size: 16px; border: none; cursor: pointer; } /* Dropdown button on hover & focus */ .dropbtn:hover, .dropbtn:focus { background-color: #2980B9; } /* The container <div> - needed to position the dropdown content */ .dropdown { position: relative; display: inline-block; } /* Dropdown Content (Hidden by Default) */ .dropdown-content { position: absolute; background-color: #f1f1f1; min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; } /* Links inside the dropdown */ .dropdown-content a { color: black; padding: 12px 16px; text-decoration: none; display: block; } /* Change color of dropdown links on hover */ .dropdown-content a:hover {background-color: #ddd} /* Add or remove this to hide or show */ .hide {display:none;} 
 <div class="dropdown"> <button class="dropbtn">Dropdown</button> <div class="dropdown-content hide"> <a href="#">Link 1</a> <a href="#">Link 2</a> <a href="#">Link 3</a> </div> </div> <div class="dropdown"> <button class="dropbtn">Dropdown</button> <div class="dropdown-content hide"> <a href="#">Link 1</a> <a href="#">Link 2</a> <a href="#">Link 3</a> </div> </div> <div class="dropdown"> <button class="dropbtn">Dropdown</button> <div class="dropdown-content hide"> <a href="#">Link 1</a> <a href="#">Link 2</a> <a href="#">Link 3</a> </div> </div> 

不幸的是,我还没有足够的声誉来评论其他人的帖子。 我想赞同在我面前发布的@Scott Marcus的做法。 我只有几个部分,我会采取不同的方式

// I would use an IIFE to scope the variable "isOpen" that will be declared next
(function () {
    // I would declare a variable isOpen to determine whether any menu is open or not (we will use this later to check whether we run the function on document click or not to save unnecessary executions)
    var isOpen = false;
    function hideAllMenus() {
        Array.prototype.slice.call(document.querySelectorAll(".dropdown-content")).forEach(function(dropdown) {
           // we dont need to check here whether our dropdown has already the class "hide" or not. the engine takes care of this anyway. there won't be a second class added in case it already has one.
           dropdown.classList.add('hide');
        });
        isOpen = false; // set to false if the function ran
    }

    // close the dropdown menu if the user clicks outside of it
    document.addEventListener("click", function (event) {
        // only run this function if any menu is actually open
        if (isOpen) {
            hideAllMenus();      // Hide all the menus
        }

        // If the clicked item was a menu
        if (event.target.classList.contains('dropbtn')) { 
            event.target.nextElementSibling.classList.toggle("hide"); // Show the one that was clicked
            isOpen = true; // set to true because now one is open
        }
    });
})();

我把它放在一起: https//codepen.io/anon/pen/dLJjrw

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM