单击锚标记时隐藏导航(香草 JavaScript)

Hide nav when clicking on anchor tags (Vanilla JavaScript)

我有一个在小屏幕上显示的导航。我的目标是每次单击其中的锚标记时隐藏该导航。 到目前为止,我已经尝试了多种选择,但其中 none 似乎有效。我认为这里真正的问题是我不知道如何 select 菜单中的所有锚标记。我正在寻找的解决方案必须是纯 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();
});
};

谢谢大家的回复,终于明白问题出在哪里了。我已经尝试了您所有的解决方案,它们运行良好。

在选项 1 中,returns 在 运行 querySelectorAll 之后是一个 nodeList which is similar to an array. You can't add an event listener to the list itself, you'll need to add the listener to each item in the list similar to what you've attempted to do in option 3. In option 2, it is the same problem, but this time with an HTMLCollection。在选项 3 中,您完成了 querySelector 而不是 querySelectorAll,后者仅 returns 与选择器匹配的第一个元素。因此,如果您使用 querySelectorAll 尝试选项 3,它应该可以工作。

当您使用 getElementsByTagName 时,它 returns 是一个节点集合,而不是 HTMLElement,因此您需要循环它以向每个元素添加事件侦听器

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

querySelector 相同,它 returns 一个 HTMLElement(只有一个),如果您希望它们全部使用 querySelectorAll,您需要将其传递给 CSS选择器

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

我使用数组传播 [...arraish_element] 为节点集合提供了真正数组的所有方法,并能够在那里使用映射,或者您可以只使用具有节点集合长度的 for

我们将采用选项 3,因为它最接近解决方案。

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

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

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