JavaScript: 调整笔记本浏览器大小 window ("mobile"--"desktop"--"mobile") 不重启菜单状态

JavaScript: Resizing laptop's browser window ("mobile"--"desktop"--"mobile") doesn't reboot menu state

我使用最新的 Google Chrome 并且我在我的 WordPress 网站中使用了以下用于响应式导航菜单的前端代码。

单击 .burger 元素会使相邻的 .menu 元素分别在下拉列表或下拉菜单中出现或消失。

我的问题

  1. 我们打开浏览器 window <=959px 我们打开移动菜单。
  2. 我们将 window 的大小调整为 >=960px,然后我们将大小调整回 <=959px
  3. 我们必须单击 burger 两次才能关闭菜单,然后重新打开它。

我的问题

为什么我们需要在给定的情况下点击两次汉堡?

代码

document.addEventListener('DOMContentLoaded', ()=>{
    let clicks = 0;
    let menu = document.querySelector('#menu-primary');
    let burger = document.querySelector('.burger');
    let isMenuVisible = false;

    burger.addEventListener('click', ()=>{
      isMenuVisible = !isMenuVisible;
      menu.style.display = isMenuVisible ? 'block' : 'none';
    });

    let mobileBehavior = ()=>{
      menu.style.display = 'none';
    };

    if (window.innerWidth <= 959) {
      mobileBehavior();
    }

    window.addEventListener('resize', ()=>{
      if (window.innerWidth <= 959) {
        clicks = 1;
      } else if (window.innerWidth >= 960) {
        menu.style.display = 'block';
      }
    });
});
.burger {
    display: block;
    text-align: center; color: var(--w);
    margin-bottom: 0 !important;
    font-weight: bold
}

#menu-primary { display: none }

@media screen and (min-width: 960px) {
    .burger { display: none }
    #menu-primary { display: block }
}
<div class="burger">BARS</div>

<ul id="menu-primary">
  <li>Homepage</li>
  <li>Contact_us</li>
</ul>

问题是当浏览器宽度最初调整为 <= 959 时您没有关闭菜单。为了有效地做到这一点,您只需要一个布尔变量来控制菜单关闭,这样它只会在断点处发生一次,然后在浏览器宽度调整为 >= 960.

时重置
document.addEventListener('DOMContentLoaded', () => {
  const menu = document.querySelector('#menu-primary');
  const burger = document.querySelector('.burger');
  const breakpoint = 959;
  let switched = false;

  burger.addEventListener('click', () => {
    menu.style.display = menu.style.display !== 'block' ? 'block' : 'none';
  });

  if (window.innerWidth <= breakpoint) {
    menu.style.display = 'none';
    switched = true;
  }

  window.addEventListener('resize', () => {
    if (window.innerWidth <= breakpoint) {
      if (!switched) {
        switched = true;
        menu.style.display = 'none';
      }
    } else {
      if (switched) {
        switched = false;
        menu.style.display = 'block';
      }
    }
  });
});

如果你想定位某个断点并且 运行 一些代码在调整大小时命中它,你可以使用 window.matchMedia 并且它也适用于断点范围。

window.addEventListener("resize", function () {

    // single breakpoint
    if (window.matchMedia("(max-width:768px)").matches) {
        // your logic here        
    }

    // you can target breakpoint range as well
    // window.matchMedia("(min-width:375px) and (max-width:768px)").matches

});

附带说明一下,如果您要执行昂贵的 dom 操作,则可能需要 throttle resize event

您使用了太多 javascript,您可以通过在单击该栏并将 'logic' 放入 css 时切换元素上的 class 来简化它.

document.addEventListener('DOMContentLoaded', ()=>{
    let menu = document.querySelector('#menu-primary');
    let burger = document.querySelector('.burger');

    burger.addEventListener('click', ()=>{
      menu.classList.toggle('collapse');
    });
});
.burger {
    display: block;
    text-align: center; color: var(--w);
    margin-bottom: 0 !important;
    font-weight: bold;
    cursor: pointer;
}
#menu-primary.collapse{
  display: none;
}

@media screen and (min-width: 960px) {
  .burger { display: none }
  #menu-primary.collapse{
    display: block;
  }
}
<div class="burger">BARS</div>

<ul id="menu-primary">
  <li>Homepage</li>
  <li>Contact_us</li>
</ul>

如果我理解了这个问题,您正在尝试完成以下任务:

  1. 创建在 click 事件时打开和关闭的汉堡包样式下拉菜单或导航抽屉。
  2. 仅在移动屏幕上显示汉堡包和相关菜单。
  3. 如果在汉堡菜单打开时将移动设备大小的屏幕调整为桌面大小:a) 汉堡菜单和相关菜单都被隐藏,并且 b) 菜单显示被“重置”,这样如果屏幕调整回移动尺寸显示汉堡包但不显示相关菜单。

其他答案已解决上述一项或多项,但并非全部。以下是将它们放在一起的方法;但是,我建议不要实施上面的“3b”,除非你的应用程序或网站有一个不寻常的用例(我认为大多数临时用户不会经常将他们的屏幕从移动设备调整到桌面设备然后又回到移动设备尺寸,但是也许我错了,我不知道如果有人确实经历过这种调整大小的实验,下拉菜单是否仍然可见会有多大关系。

我添加了一些额外的 htmlcss 用于样式目的,因为很难直观地看到切换菜单显示和使用 spartan 设置调整屏幕大小的效果(也处理了使用 visibility 属性和 position: absolute 显示菜单,以便在切换显示时不会影响其他元素的定位。

针对您特定用途的功能代码是 javascript 和 css 样式 .burger.burger-menu.hidden.desktop 类(包括相关的媒体查询)。

const burger = document.querySelector('.burger');
const burgerMenu = document.querySelector('.burger-menu');
burger.addEventListener('click', () => {
  burgerMenu.classList.toggle('hidden');
});

// not recommended (but this "resets" the menu display on resize)
window.addEventListener("resize", () => {
  if (window.matchMedia('(min-width:960px)').matches) {
    burgerMenu.classList.add('hidden');
  }
});
nav {
  background-color: #000;
  color: #fff;
  margin-bottom: 16px;
}

nav ul:first-child {
  display: inline;
  padding: 0;
}

nav ul li {
  padding: 8px 16px;
}

.burger {
  display: inline-block;
}

.burger div {
  background-color: #fff;
  margin: 4px 0;
  width: 24px;
  height: 3px;
}

.burger-menu {
  background-color: #000;
  padding: 4px;
  position: absolute;
  list-style: none;
}

.hidden {
  visibility: hidden;
}

.desktop {
  display: none;
}

@media screen and (min-width: 960px) {
  .burger {
    display: none;
  }
  .burger-menu {
    visibility: hidden;
  }
  .desktop {
    display: inline-block;
  }
}
<nav>
  <ul>
    <li class="burger">
      <div></div>
      <div></div>
      <div></div>
    </li>
    <ul class="burger-menu hidden">
      <li>Home (mobile)</li>
      <li>Contact (mobile)</li>
    </ul>
    <li class="desktop">Home (desktop)</li>
    <li class="desktop">Contact (desktop)</li>
  </ul>
</nav>
<div>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vel augue ipsum. Donec suscipit nisi magna, ac condimentum est blandit a.
</div>