单击某处后隐藏导航无法正常工作

Hiding navigation after clicking somewhere esle not working correctly

我有一个汉堡导航。单击汉堡侧边栏导航后显示并再次单击后隐藏。我想做到这一点,所以我不必点击汉堡按钮,但我可以点击其他地方(主容器等)并隐藏侧边栏。 这是汉堡按钮代码:

function navBurger() {
    var element = document.querySelector(".navbar");
    var burger = document.querySelector(".burger-btn");
    element.classList.toggle("extended");
    burger.classList.toggle("open");
}

这部分工作得很好,但是当我添加这个时:

window.onclick = function() {
    var element = document.querySelector(".navbar");
    var burger = document.querySelector(".burger-btn");
    
    if (element.classList.contains("extended")) {
        window.onclick = function() {
            element.classList.remove("extended");
            burger.classList.remove("open");
        }
    } 
}

导航会在第一次点击后隐藏,但我无法在第一次点击后显示然后隐藏它。这就像脚本认为导航仍然有 class (但它已被删除)并且不会让导航栏打开。 有办法解决吗?

问题的原因是全局点击处理程序将自身替换为嵌套的无条件函数来关闭汉堡菜单。第二次单击将打开菜单,但会冒泡到 window 处理程序并再次将其关闭。

全局处理程序需要在关闭扩展菜单之前确定点击是在扩展菜单内部还是外部。将 closest 方法应用于点击事件目标可以帮助解决这个问题。

window.onload = function() {
    var element = document.querySelector(".navbar");
    var burger = document.querySelector(".burger-btn");
    window.onclick = function(event) {
        if( burger.classList.contains("open") 
          && !event.target.closest(".extended") ) {
            // the click is outside an open extended element
            element.classList.remove("extended");
            burger.classList.remove("open");
        }    
    };
};

如果用户在带有 class "extended" 的元素外单击,上面应该关闭汉堡菜单。 JQuery 文档涵盖 jQuery closest 方法和 event.target 如果您想在 jQuery.

中编写代码

注意设置 window.onclickwindow.onload 中设置以避免混淆,并且使用 oneventname 元素属性更好地替换为在 [=30] 中使用 addEventListener 调用=].

在您的原始代码中,在第一次点击打开导航后,window onclick 将删除通过点击菜单按钮添加的 类 作为事件冒泡。要解决此问题,请将 event.stopPropagation() 添加到您的菜单点击处理程序。

https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation

我还删除了 onclick 处理程序的 re-bind,因为它导致第一次单击无法正确关闭菜单。

function navBurger(e) {
    console.log('button clicked')
    var element = document.querySelector(".navbar");
    var burger = document.querySelector(".burger-btn");
    element.classList.toggle("extended");
    burger.classList.toggle("open");
    // Prevents the window onclick from firing after this function runs
    // try commenting this out
    e.stopPropagation();
}

window.onclick = function() {
    console.log('onclick triggered');
    var element = document.querySelector(".navbar");
    var burger = document.querySelector(".burger-btn");
    
    if (element.classList.contains("extended")) {
        element.classList.remove("extended");
        burger.classList.remove("open");
    } 
}

document.querySelector(".burger-btn").addEventListener("click", navBurger);
.navbar.extended {
  background: green;
}

.burger-btn.open::after {
  content: "Open";
  display: inline;
}
<nav class="navbar"><button class="burger-btn" type="button">Nav</button></nav>