簡體   English   中英

單擊父級時在菜單中顯示/隱藏子級(使用純 JavaScript)

[英]Show/Hide children in menu when clicking on parent (with pure javascript)

我對 JavaScript 有基本的了解,我正在嘗試創建一個菜單,其中:

  • 只有第一級父母是可見的。
  • 然后,當您單擊它們時,將顯示它們的子項。
  • 如果您再次單擊它們(或者單擊頁面上的任何位置),它們將關閉
  • 必須為 2 個級別的孩子工作(例如孩子的孩子)

這是我到目前為止所擁有的,我知道這遠非正確。 我在網上找到了一堆 jQuery 解決方案,但我想要它純 JavaScript & CSS。

注意:我還需要將使用的類和 ID 的數量保持在最低限度,因為我希望能夠將其與 WordPress 菜單結構一起使用。 但是,如果我需要為每個有孩子的父母手動添加一個“父母”class,那就沒問題了。

我的 JavaScript:

var menuParents = document.querySelectorAll("#my-menu .parent");
menuParents.forEach(menuParent => {
   document.querySelector("#my-menu .parent").addEventListener("click", ToggleMenu);
      function ToggleMenu() {
         document.querySelector("#my-menu .parent ul").style.display = 'block';
      }
});

我的 CSS:

#my-menu .parent ul {display: none;}

最后,我的 HTML:

<ul id="my-menu">
   <li>Standard Item</li>
   <li>Standard Item</li>
   <li class="parent">Item with children
      <ul>
         <li>child item</li>
         <li>child item</li>
         <li class="parent">child item with children
           <li>second level child</li>
           <li>second level child</li>
         </li>
         <li>child item</li>
         <li>child item</li>
      </ul>
   </li>
   <li>Standard Item</li>
   <li>Standard Item</li>
   <li class="parent">Item with children
      <ul>
        <li>child item</li>
        <li>child item</li>
        <li class="parent">child item with children
           <li>second level child</li>
           <li>second level child</li>
        </li>
        <li>child item</li>
        <li>child item</li>
      </ul>
   </li>
   <li>Standard Item</li>
   <li>Standard Item</li>
</ul>

您需要使用forEach中的特定元素,然后只需獲取它的firstElementChild ,並切換display樣式:

 const toggle = { block: 'none', none: 'block' } function ToggleMenu(event) { event.stopPropagation(); event.target.classList.toggle('active'); event.target.firstElementChild.style.display = toggle[event.target.firstElementChild.style.display] || 'block'; } var menuParents = document.querySelectorAll("#my-menu.parent"); menuParents.forEach(menuParent => { menuParent.addEventListener("click", ToggleMenu); })
 #my-menu.parent ul {display: none;}.active { color: red }.active > * { color: black }
 <ul id="my-menu"> <li>Standard Item</li> <li>Standard Item</li> <li class="parent">Item with children <ul> <li>child item</li> <li>child item</li> <li class="parent">child item with children <ul> <li>second level child</li> <li>second level child</li> </ul> </li> <li>child item</li> <li>child item</li> </ul> </li> <li>Standard Item</li> <li>Standard Item</li> <li class="parent">Item with children <ul> <li>child item</li> <li>child item</li> <li class="parent">child item with children <ul> <li>second level child</li> <li>second level child</li> </ul> </li> <li>child item</li> <li>child item</li> </ul> </li> <li>Standard Item</li> <li>Standard Item</li> </ul>

或沒有“父” class

 const toggle = { block: 'none', none: 'block' } function ToggleMenu(event) { event.stopPropagation(); if (event.target.firstElementChild) { event.target.classList.toggle('active'); event.target.firstElementChild.style.display = toggle[event.target.firstElementChild.style.display] || 'block'; } } var menuParents = document.querySelectorAll("#my-menu li > ul"); menuParents.forEach(menuParent => { menuParent.parentElement.addEventListener("click", ToggleMenu); })
 #my-menu li > ul {display: none;}.active { color: red }.active > * { color: black }
 <ul id="my-menu"> <li>Standard Item</li> <li>Standard Item</li> <li>Item with children <ul> <li>child item</li> <li>child item</li> <li>child item with children <ul> <li>second level child</li> <li>second level child</li> </ul> </li> <li>child item</li> <li>child item</li> </ul> </li> <li>Standard Item</li> <li>Standard Item</li> <li>Item with children <ul> <li>child item</li> <li>child item</li> <li>child item with children <ul> <li>second level child</li> <li>second level child</li> </ul> </li> <li>child item</li> <li>child item</li> </ul> </li> <li>Standard Item</li> <li>Standard Item</li> </ul>

你的 HTML 有點錯誤:你父母里面的父母沒有ul元素。

<ul id="my-menu">
    <li>Standard Item</li>
    <li>Standard Item</li>
    <li class="parent">Item with children
        <ul>
            <li>child item</li>
            <li>child item</li>
            <li class="parent">child item with children
                <!-- here -->
                <ul>
                    <li>second level child</li>
                    <li>second level child</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>child item</li>
    <li>child item</li>
    <li>Standard Item</li>
    <li>Standard Item</li>
    <li class="parent">Item with children
        <ul>
            <li>child item</li>
            <li>child item</li>
            <li class="parent">child item with children
                <!-- and here -->
                <ul>
                    <li>second level child</li>
                    <li>second level child</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>child item</li>
    <li>child item</li>
    <li>Standard Item</li>
    <li>Standard Item</li>
</ul>

JavaScript 明智,您的切換 function 實際上並沒有切換任何東西,或者它不會切換超過一次,無論如何。

另一個問題是,當您單擊父級的父級時,也會調用單擊處理程序,這段代碼也說明了這一點。

這里我使用了一個匿名的 function。 您不必這樣做,命名為 function 可以正常工作,但它不會弄亂您唯一的命名空間。

這也適用於任何級別的父母:附加的片段具有二級父母。

var menuParents = document.querySelectorAll("#my-menu .parent");
menuParents.forEach(
    menuParent => {
        menuParent.addEventListener(
            "click",
            // inline, anonymous function
            //  also accepts an event parameter
            function (event) {
                // check if the parent element was actually clicked (prevent parent of parent from toggling display)
                if (event.target == this) {
                    // this == menuParent
                    // select ul from menuParent
                    var menuChild = this.querySelector("ul");

                    // toggle child menu display, based on it's current display
                    if (menuChild.style.display == "block") {
                        // here, you could also set the display to null, since your CSS sets the display to none anyway
                        menuChild.style.display = "none";
                    } else {
                        menuChild.style.display = "block";
                    }
                }
            }
        );
    }
);

在 Chrome 87.0.4280.88 上測試。

 var menuParents = document.querySelectorAll("#my-menu.parent"); menuParents.forEach( menuParent => { menuParent.addEventListener( "click", // inline, anonymous function // also accepts an event parameter function (event) { if (event.target == this) { // this == menuParent // select ul from menuParent var menuChild = this.querySelector("ul"); // toggle child menu display, based on it's current display if (menuChild.style.display == "block") { // here, you could also set the display to null, since your CSS sets the display to none anyway menuChild.style.display = "none"; } else { menuChild.style.display = "block"; } } } ); } );
 #my-menu.parent ul { padding-left: 16px; display: none; }
 <ul id="my-menu"> <li>Standard Item</li> <li>Standard Item</li> <li class="parent">Item with children <ul> <li>child item</li> <li>child item</li> <li class="parent">child item with children <ul> <li>second level child</li> <li>second level child</li> <li class="parent">second level parent <ul> <li>third level child</li> <li>third level child</li> </ul> <li>second level child</li> <li>second level child</li> </ul> </li> <li>child item</li> <li>child item</li> </ul> </li> </li> <li>Standard Item</li> <li>Standard Item</li> <li class="parent">Item with children <ul> <li>child item</li> <li>child item</li> <li class="parent">child item with children <ul> <li>second level child</li> <li>second level child</li> <li class="parent">second level parent <ul> <li>third level child</li> <li>third level child</li> </ul> </li> <li>second level child</li> <li>second level child</li> </ul> </li> <li>child item</li> <li>child item</li> </ul> </li> <li>Standard Item</li> <li>Standard Item</li> </ul>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM