JavaScript:调整笔记本电脑的浏览器窗口大小(“移动” - “桌面” - “移动”)不会重启菜单状态

问题描述 投票:2回答:4

我使用最新的谷歌浏览器,我有一个响应式导航菜单的以下前端代码,我在我的WordPress网站上使用。

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

我的问题

  1. 我们打开浏览器窗口<=959px,然后打开手机菜单。
  2. 我们调整窗口大小到>=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;
        menu.style.display = 'none';
      } 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>
javascript html css browser resize
4个回答
2
投票

问题是,当浏览器宽度最初调整为<= 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';
      }
    }
  });
});

2
投票

你使用了太多的javascript,你可以通过在单击该栏并在css中放置'逻辑'时在元素上切换一个类来简化它。

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
投票

如果你想定位某个断点并在调整大小时运行一些代码,你可以使用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


0
投票

如果我理解了这个问题,那么您正在努力完成以下任务:

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

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

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

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

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>
© www.soinside.com 2019 - 2024. All rights reserved.