【问题标题】:why mobile menu won't work on first click, but works fine on subsequent clicks?为什么移动菜单在第一次点击时不起作用,但在后续点击时可以正常工作?
【发布时间】:2021-06-09 00:41:36
【问题描述】:

我正在尝试使用 JS 和 css 为我的网站制作一个移动菜单,当我第一次点击按钮时它没有响应,但在随后的点击中它工作正常,而且第一个菜单也有一点延迟在随后的点击中消失。

这些可能是什么原因?

我试图控制台记录网页开头的“top”属性,但它给出了空白空间,然后频繁点击给出“-110%”或“60px”的值 html

const mobile = window.matchMedia("max-width: 768px;");
let menu = document.querySelector(".aside");

if (mobile.matches) {
  document.querySelector(".scroll").addEventListener(onclick, toggleMenu());
}

function toggleMenu() {

  if (menu.style.top == "-110%") {
    menu.style.top = "60px";
  } else {
    menu.style.top = "-110%";
  }
}
header {
  height: 60px;
  position: relative;
  background-color: #fcf1ee;
  z-index: 2;
}

.mobile-menu-button {
  position: absolute;
  top: 20px;
  right: 20px;
  display: inline-block;
  width: 40px;
  height: 40px;
  background: linear-gradient(to bottom right, #5cebb5 0%, #225139 84%);
  border-radius: 5px;
  border-color: #448d76;
  cursor: pointer;
}

.aside {
  width: 90%;
  margin: 0 5%;
  background: linear-gradient( to bottom right, rgba(68, 141, 118, 0.9) 0%, rgba(53, 121, 86, 0.9) 76%);
  box-shadow: 10px 20px 50px rgba(0, 0, 0, 0.8);
  border-radius: 7px;
  position: absolute;
  left: 0;
  top: -110%;
  transition: 1s;
  z-index: 1;
}
<header>
  <button class="mobile-menu-button scroll" onClick="toggleMenu()"><i class="fas fa-bars"></i>
 </button>
</header>
<div class="aside">
  <div class="avatar-container">
    <div class="avatar"></div>
  </div>
  <nav>
    <ul>
      <li>
        <a href="#" class="scroll" data-value="about">
        About
        </a>
      </li>
      <li>
        <a href="#" class="scroll" data-value="resume">
        Resume
        </a>
      </li>
      <li>
        <a href="#portfolio" class="scroll" data-value="portfolio">
        Portfolio
        </a>
      </li>
      <li>
        <a href="#contact" class="scroll" data-value="contact">
        Contact
        </a>
      </li>
    </ul>
  </nav>
</div>

【问题讨论】:

    标签: javascript css


    【解决方案1】:

    这个检查:

    if (menu.style.top == "-110%")
    

    从字面上检查元素上的style 属性。因为你没有那个 - 它在第一次点击时评估为false

    【讨论】:

    • 谢谢,这正是我所缺少的,我以为它改变了 css 文件。
    【解决方案2】:

    obe 是对的,但如果您仍然想要一个解决方案,那么您可以使用以下方法:

    if (menu.style.top == "-110%" || menu.style.top == "") {
       menu.style.top = "60px";
    } else {
       menu.style.top = "-110%";
    }
    

    这将在第一次点击时起作用,最高值将始终为“”。

    【讨论】:

    • 我没有提供解决方案,因为没有请求解决方案,而且这个解决方案还不错,但我建议看看@sloont 的建议。从长远来看,他的方法更简洁、更具表现力且更易于维护(尽管我会对其进行一些更改,并且不依赖于 menu.classList 中的特定索引)
    • 我完全同意你的看法。 @MohamadHasan 是 sloont 建议的一种更好的方法来实现此功能。
    • 我一定会研究sloont的解决方案,我只是需要更多的JS学习。
    【解决方案3】:

    看起来你已经得到了一些很好的答案,但我已经研究了一分钟,所以我会发布我所做的。

    我添加了类,以便您可以根据菜单的外观将它们用于其他样式。

    这是codesandbox

    在html页面中,我只是在内容周围添加了&lt;body&gt;。在我的示例中,我还从 html 中的按钮中删除了 onClick 属性。

    在 JS 中,我清理了它并删除了 mobile 变量,因为您不需要它在浏览器中进行测试。您可以轻松地将其添加回脚本以仅测试移动设备。

    let button = document.getElementsByClassName("scroll")[0];
    let menu = document.getElementsByClassName("aside")[0];
    
    const toggleMenu = function () {
      console.log("button clicked");
    
      if (menu.classList.length === 1) {
        return menu.classList.add("active");
      }
    
      if (menu.classList[1] === "active") {
        return menu.classList.replace("active", "inactive");
      }
    
      if (menu.classList[1] === "inactive") {
        return menu.classList.replace("inactive", "active");
      }
    };
    
    button.addEventListener("click", () => toggleMenu());
    

    肯定有一种方法可以只使用 "active" 的类,但看起来几乎相同。

    CSS 是最重要的变化。我们添加了适用于top 属性的transition 属性。

    .aside {
      width: 90%;
      margin: 6rem 5% 0 5%;
      background: linear-gradient(
        to bottom right,
        rgba(68, 141, 118, 0.9) 0%,
        rgba(53, 121, 86, 0.9) 76%
      );
      box-shadow: 10px 20px 50px rgba(0, 0, 0, 0.8);
      border-radius: 7px;
      position: absolute;
      left: 0;
      top: -110%;
      z-index: 1;
    }
    
    .aside.active {
      top: 0% !important;
      transition: top 1s;
    }
    .aside.inactive {
      top: -110% !important;
      transition: top 1s;
    }
    
    

    activeinactive 类应用于aside 类的元素时,top 属性被覆盖,transition 属性触发其功能。

    我希望这会有所帮助。如果您有任何问题,请告诉我!

    【讨论】:

    • 谢谢,我明白了你的代码背后的逻辑,(添加一个类来做我想要的菜单)除了我还在 JS 中迈出第一步,所以我必须了解更多关于你在这里使用的函数。
    【解决方案4】:

    menu.style.top 第一次没有返回。它不查看 css,而是查看 html 中的样式属性(不存在)。

    一个简单的解决办法是:

    function toggleMenu() {
      if (menu.style.top == "60px") {
        menu.style.top = "-110%";
      } else {
        menu.style.top = "60px";
      }
    }
    

    并将其他所有内容都保留在您的问题中。

    基本上,第一次使用您的代码不会改变任何内容,因为“else”是当前状态。通过围绕第一次点击旋转它们实际上会在那里拥有另一种状态。

    jsfiddle:https://jsfiddle.net/nf49d7me/

    一个简单的调试方法是添加一个:

    alert(menu.style.top);
    

    在 toggleMenu 函数中。您将看到它使用的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-15
      • 1970-01-01
      • 2023-04-07
      • 2017-08-19
      • 2016-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多