单击锚标签时隐藏导航(Vanilla JavaScript)

时间:2018-01-11 23:04:01

标签: javascript nav dom-events

我有一个显示在小屏幕上的导航。我的目标是每次点击其中的锚标签时隐藏该导航。 到目前为止,我已经尝试了多种选择,但它们似乎都没有效果。我认为这里真正的问题是我不知道如何选择菜单中的所有锚标签。我看的解决方案必须是纯JS。提前谢谢。

<nav id="mySidenav" class="sidenav">
               <a href="#about">About</a>
               <a href="#services" onclick="closeNav();">Services</a>
               <a href="#contact">Contact</a>
</nav>



.sidenav {
          width: 0;
         }
.sidenav.mobile-only {
         width:250px;
                     }

function closeNav() {
   myNav.classList.remove("mobile-only");
 }

选项1

 var anchorTags = document.querySelectorAll('a')
 anchorTags.addEventListener('click', closeNav(), false);
 ** Uncaught TypeError: anchorTags.addEventListener is not a function

选项2

 var anchorTags = document.getElementsByTagName("a")
 anchorTags.addEventListener('click', closeNav());
 **Uncaught TypeError: anchorTags.addEventListener is not a function

选项3

 var anchorTags = document.querySelector("mobile-only a");
    for (var x = 0; x < anchorTags.length; x++) {
        anchorTags[x].addEventListener("click", function() {
            closeNav();
    });
    };

    **Uncaught TypeError: Cannot read property 'length' of null

我发现的唯一解决方案是内联添加功能,但我确信必须有更好的解决方案。

<a href="#about" onclick="closeNav();">About</a>
<a href="#services" onclick="closeNav();">Services</a>
<a href="#contact" onclick="closeNav();">Portofolio</a>

稍后编辑: 选项4:获胜者(下面列出了比这更好的解决方案。谢谢大家)

var anchorTags = document.getElementById("mySidenav").childNodes;
for (var x = 0; x < anchorTags.length; x++) {
    anchorTags[x].addEventListener("click", function() {
        closeNav();
});
};

感谢大家的回复,我终于明白了问题所在。我已经尝试了所有的解决方案,而且效果很好。

3 个答案:

答案 0 :(得分:0)

在选项1中,运行querySelectorAll后返回的是nodeList,类似于数组。您无法向列表本身添加事件侦听器,您需要将侦听器添加到列表中的每个项目,类似于您在选项3中尝试执行的操作。在选项2中,这是同样的问题,但这次是HTMLCollection。在选项3中,您已完成querySelector而不是querySelectorAll,它只返回与选择器匹配的第一个元素。因此,如果您使用querySelectorAll尝试选项3,它应该可以正常工作。

答案 1 :(得分:0)

使用getElementsByTagName时它返回的是一个Node集合,而不是一个HTMLElement,因此你需要循环它以向每个元素添加事件监听器

var anchorTags = document.getElementsByTagName("a");
[...anchorTags].map(elem => elem.addEventListener('click', closeNav));

querySelector相同,它返回一个HTMLElement(只有一个),如果你想要它们都使用querySelectorAll,你需要传递一个CSS选择器

var anchorTags = document.querySelector("a.mobile-only");
[...anchorTags].map(elem => elem.addEventListener('click', closeNav));

我使用数组传播[...arraish_element]为节点集合提供了一个真正数组的所有方法,并且能够在那里使用map,或者你只需​​要使用带有nodecollection长度的for

答案 2 :(得分:0)

我们将继续使用选项3,因为它适用于解决方案。

您应该使用document.querySelectorAll('nav a')甚至更好document.querySelectorAll('.sidenav a')。这将为您提供与我们的选择器匹配的所有元素的节点列表。之后,我们可以使用forEach遍历每个节点并绑定我们的点击事件。

document.querySelectorAll('.sidenav a').forEach(function(a) {
    a.addEventListener('click', closeNav);
});

请注意,我使用closeNav代替closeNav() - ()非常重要!使用()将尝试立即调用该函数,而不是将该函数指定为事件的处理程序。