在外部设置显示样式会导致onclick()事件初始化两次点击

Setting display styles externally causes an onclick() event TWO clicks to initialise

本文关键字:初始化 事件 两次 onclick 显示 设置 外部 样式      更新时间:2023-09-26

为什么我们必须在HTML上设置display: none;内联而不是外部,以便onclick()事件在第一次点击时工作,在第一次。

通过外部设置,代码可以工作,但需要两次点击来初始化,一次设置事件处理程序,一次触发事件处理程序。我的代码:

function submenu() {
  Menu = document.getElementById('menu');
  sub = document.getElementById('sub');
  function display() {
    if (sub.style.display === 'none') {
      sub.style.display = "inline-block";
    } else {
      sub.style.display = "none";
    }
  }
  Menu.addEventListener('click', display);
}
function pageLoad() {
  submenu();
}
nav {
  position: relative;
  margin: 0 auto;
  top: -60%;
  left: 24%;
  display: block;
  width: 33%;
  height: 20%;
}
nav ul {
  list-style-type: none;
  width: 100%;
  display: block;
}
nav ul li {
  width: 100%;
  color: #888;
  z-index: 0;
  display: block;
  font-size: 1.5em;
}
nav ul li a {
  text-decoration: none;
  color: #888;
}
#sub {
  width: 120%;
  position: absolute;
  top: 230%;
  z-index: 1;
  display: none;
  background-color: rgba(51, 51, 51, 0.8);
  margin: 0 auto;
}
#sub li {
  margin-top: 3px;
  padding: 2px;
  width: 100%;
  opacity: 2;
}
<nav>
  <ul>
    <li id="menu"> - Menu - </li>
    <ul id="sub">
      <li><a href="#methods">Services</a></li>
      <li><a href="#aftercare">Aftercare</a></li>
      <li><a href="#about">About Me</a></li>
      <li><a href="#contact">Contact Me</a></li>
    </ul>
    </li>
  </ul>
</nav>

需要两次点击来初始化然后工作,但在更改以下行之后,每次都要先点击:

HTML的变化:

<nav id="menu">
<ul id="sub" style="display: none;">
CSS改变:

#sub {
        width: 120%;
        position: absolute;
        top: 230%;
        z-index: 1;
        background-color: rgba(51,51,51,0.8);
        margin: 0 auto;
    }

对于javascript代码,我将函数添加到window中。onload:

window.onload = pageLoad;
function pageLoad() {
    submenu();
}

所以除非我改变样式display: none;内联CSS,它仍然需要两次点击。我想更好地理解为什么会发生这种情况。我试着在谷歌上寻找一个解释,但没有收到任何东西。

如果你在CSS中设置display的样式,那么从sub.style.display开始将是一个空字符串,但是如果你使用style属性在元素上设置它,那么它将具有你给它的值。你可以通过检查值是否为空字符串来解决这个问题,但随后你必须弄清楚这对你的应用程序意味着什么(基于CSS中的初始值)。

我想在这里提出一个替代方案,它也应该很好地服务于其他场景,并且不需要您更改style属性,而是依赖于更改元素的类。

如果你要添加一些CSS来隐藏默认的子菜单,并添加一个类来将菜单切换为可见:

nav ul ul { 
    display: none; 
}
nav .active {
    display: block;
}
用下面的JS来切换类
var menu = document.getElementById('menu');
var sub = document.getElementById('sub');
function toggleMenu(){
    sub.classList.toggle('active');
}
menu.addEventListener('click', toggleMenu);

通过这种方式,你可以很容易地调整你的代码来为多个子菜单做到这一点,所以这里是另一个更通用的例子,允许你有多个菜单和子菜单。

HTML

<nav class="menu">
    <ul>
        <li class="parent"> - Menu 1 -
            <ul>
                <li><a href="#sub">sub menu 1</a></li>
                <li><a href="#sub">sub menu 1</a></li>
            </ul>
        </li>
        <li class="parent"> - Menu 2 -
            <ul>
                <li><a href="#sub">sub menu 2</a></li>
                <li><a href="#sub">sub menu 2</a></li>
            </ul>
        </li>
    </ul>
</nav>
CSS

.menu ul ul { display: none; }
.menu .active {
    display: block;
}

JS

var menus = document.querySelectorAll('.menu');
function toggleMenu(e){
    var target = e.target;
    // only care about clicks on parent list items.
    if (target.className.indexOf('parent') === -1) {
        return;
    }
    // use querySelector to find the first <ul> inside this parent <li>
    var submenu = target.querySelector('ul');
    if (submenu) {
        submenu.classList.toggle('active');
    }
}
// add a click handler to each menu
menus.forEach(function(menu) {
    menu.addEventListener('click', toggleMenu);
});