如何在没有jquery的情况下创建切换下拉菜单

时间:2022-11-20 07:31:18

I am avoiding jquery for most of my practices so I can familiarize myself with javascript but I am having a bit of trouble trying to get sub menus to toggle properly with transitions. Example of my Jfiddle My original code:

我在大多数练习中都避免使用jquery,因此我可以熟悉javascript,但是我在尝试使用子菜单切换到切换时遇到了一些麻烦。我的Jfiddle示例我的原始代码:

var submenu = document.getElementById('sub-menu');
function toggleMenu() {
  if (submenu.style.display == "none") {
    submenu.style.display = "block";
  }
  else {
    submenu.style.display = "none";
  }
};

works but it's inefficiency makes it unusable nor it's re-usability as it only works per menu and has to be reassigned id/class for the next.

虽然有效,但效率低下使其无法使用,也无法重复使用,因为它只适用于每个菜单,必须为下一个重新分配id / class。

My next idea was to user an event handler for clicks when the item-has-children is clicked but I am unsure on how to target the sub-menu of the clicked Menu.

我的下一个想法是在点击item-has-children时为用户设置一个事件处理程序,但我不确定如何定位所单击菜单的子菜单。

Any advice or redirection would be greatly appreciated.

任何建议或重定向将不胜感激。

2 个解决方案

#1


I based my answer on the code on JSFiddle. It is different from the code in the question, but both contains some JavaScript and CSS errors. For example:

我的答案基于JSFiddle上的代码。它与问题中的代码不同,但都包含一些JavaScript和CSS错误。例如:

  • document.getElementsByClassName returns an array, but you try to use it as it returns an object.
  • document.getElementsByClassName返回一个数组,但您尝试使用它,因为它返回一个对象。

  • As you apply the toggle to the outer li, it affects even when you click on the inner list (although this may be by design, it would be better on the a).
  • 当您将切换应用于外部li时,即使您单击内部列表也会影响(尽管这可能是设计上的,但在a上会更好)。

  • The CSS for the selected submenu should be .sub-menu.selected, instead of .sub-menu .selected (with a space).
  • 所选子菜单的CSS应为.sub-menu.selected,而不是.sub-menu .selected(带空格)。

  • display transitions are not supported (at least not yet afaik).
  • 不支持显示转换(至少尚未支持)。

I have modified those things, and here is a sample plain JavaScript code of what you want:

我修改了这些内容,这里是一个简单的JavaScript代码示例:

// get the array with all the links and traverse it binding the click event
var allHasChildren = document.querySelectorAll(".item-has-children a");
for (var x = 0; x < allHasChildren.length; x++) {
    allHasChildren[x].onclick = function() {
        // get the first submenu and toggle using classes
        var subMenu = this.parentNode.getElementsByClassName("sub-menu")[0];
        if (subMenu.classList.contains('selected')) {
            subMenu.classList.remove("selected");
        } else {
            subMenu.classList.add("selected");
        }
    }
}
.sub-menu {
    display: none;
}
.sub-menu.selected {
    display: block;
    transition: transform .2s;
}
<ul>
    <li class="item-has-children">
        <a href="#0">Main Item One</a>
        <ul class="sub-menu">
            <li><a href="#0">Sub Item One</a></li>
            <li><a href="#0">Sub Item Two</a></li>
            <li><a href="#0">Sub Item Three</a></li>
            <li><a href="#0">Sub Item Four</a></li>
            <li><a href="#0">Sub Item Five</a></li>
            <li><a href="#0">Sub Item Six</a></li>
        </ul>
    </li>
    <li class="item-has-children">
        <a href="#0">Main Item Two</a>
        <ul class="sub-menu">
            <li><a href="#0">Sub Item One</a></li>
            <li><a href="#0">Sub Item Two</a></li>
            <li><a href="#0">Sub Item Three</a></li>
            <li><a href="#0">Sub Item Four</a></li>
            <li><a href="#0">Sub Item Five</a></li>
            <li><a href="#0">Sub Item Six</a></li>
        </ul>
    </li>
</ul>

You can also see it on JSFiddle: http://jsfiddle.net/10j79rrf/5/

你也可以在JSFiddle上看到它:http://jsfiddle.net/10j79rrf/5/

As you can see, you can achieve what you want just using plain JavaScript, but as noted by other users, it will look uglier and take more lines of code than using a library to manipulate the DOM.

正如您所看到的,您可以使用纯JavaScript实现您想要的功能,但正如其他用户所指出的,与使用库来操作DOM相比,它看起来更加丑陋并且需要更多行代码。

#2


You can make you jQuery function re-usable, by making the selectors as general as possible. A two leveled menu has <li> with <ul> inside it. We can use that to our advantage by using the :has() selector:

通过使选择器尽可能通用,您可以使jQuery函数可重用。一个两层的菜单里面有

  • ,里面有
      。我们可以通过使用:has()选择器来使用它:

  • $('li:has(ul)').on('click', function() {
        $(this).find('ul').toggle();
    });
    

    Also see this demo.

    另见本演示。

    This script is small and usable on other of your sites as well.

    此脚本很小,也可以在您的其他网站上使用。

    #1


    I based my answer on the code on JSFiddle. It is different from the code in the question, but both contains some JavaScript and CSS errors. For example:

    我的答案基于JSFiddle上的代码。它与问题中的代码不同,但都包含一些JavaScript和CSS错误。例如:

    • document.getElementsByClassName returns an array, but you try to use it as it returns an object.
    • document.getElementsByClassName返回一个数组,但您尝试使用它,因为它返回一个对象。

    • As you apply the toggle to the outer li, it affects even when you click on the inner list (although this may be by design, it would be better on the a).
    • 当您将切换应用于外部li时,即使您单击内部列表也会影响(尽管这可能是设计上的,但在a上会更好)。

    • The CSS for the selected submenu should be .sub-menu.selected, instead of .sub-menu .selected (with a space).
    • 所选子菜单的CSS应为.sub-menu.selected,而不是.sub-menu .selected(带空格)。

    • display transitions are not supported (at least not yet afaik).
    • 不支持显示转换(至少尚未支持)。

    I have modified those things, and here is a sample plain JavaScript code of what you want:

    我修改了这些内容,这里是一个简单的JavaScript代码示例:

    // get the array with all the links and traverse it binding the click event
    var allHasChildren = document.querySelectorAll(".item-has-children a");
    for (var x = 0; x < allHasChildren.length; x++) {
        allHasChildren[x].onclick = function() {
            // get the first submenu and toggle using classes
            var subMenu = this.parentNode.getElementsByClassName("sub-menu")[0];
            if (subMenu.classList.contains('selected')) {
                subMenu.classList.remove("selected");
            } else {
                subMenu.classList.add("selected");
            }
        }
    }
    .sub-menu {
        display: none;
    }
    .sub-menu.selected {
        display: block;
        transition: transform .2s;
    }
    <ul>
        <li class="item-has-children">
            <a href="#0">Main Item One</a>
            <ul class="sub-menu">
                <li><a href="#0">Sub Item One</a></li>
                <li><a href="#0">Sub Item Two</a></li>
                <li><a href="#0">Sub Item Three</a></li>
                <li><a href="#0">Sub Item Four</a></li>
                <li><a href="#0">Sub Item Five</a></li>
                <li><a href="#0">Sub Item Six</a></li>
            </ul>
        </li>
        <li class="item-has-children">
            <a href="#0">Main Item Two</a>
            <ul class="sub-menu">
                <li><a href="#0">Sub Item One</a></li>
                <li><a href="#0">Sub Item Two</a></li>
                <li><a href="#0">Sub Item Three</a></li>
                <li><a href="#0">Sub Item Four</a></li>
                <li><a href="#0">Sub Item Five</a></li>
                <li><a href="#0">Sub Item Six</a></li>
            </ul>
        </li>
    </ul>

    You can also see it on JSFiddle: http://jsfiddle.net/10j79rrf/5/

    你也可以在JSFiddle上看到它:http://jsfiddle.net/10j79rrf/5/

    As you can see, you can achieve what you want just using plain JavaScript, but as noted by other users, it will look uglier and take more lines of code than using a library to manipulate the DOM.

    正如您所看到的,您可以使用纯JavaScript实现您想要的功能,但正如其他用户所指出的,与使用库来操作DOM相比,它看起来更加丑陋并且需要更多行代码。

    #2


    You can make you jQuery function re-usable, by making the selectors as general as possible. A two leveled menu has <li> with <ul> inside it. We can use that to our advantage by using the :has() selector:

    通过使选择器尽可能通用,您可以使jQuery函数可重用。一个两层的菜单里面有

  • ,里面有
      。我们可以通过使用:has()选择器来使用它:

  • $('li:has(ul)').on('click', function() {
        $(this).find('ul').toggle();
    });
    

    Also see this demo.

    另见本演示。

    This script is small and usable on other of your sites as well.

    此脚本很小,也可以在您的其他网站上使用。