如何使addEventListener'click'在具有相同类的两个菜单项上工作

页面:https : //ensjotannklinikk.no/

这是一把小提琴

第一个名为“ Behandlinger ”的菜单项是用这个 JS(由biberman 提供)设置的,以使子菜单正确出现和缩回。

var submenu = document.querySelector('.behandlinger-meny');
var menuTrigger = document.querySelector('.behandlinger-item');

//javascript version of jQuery isChild()
function isChild(item, parentItem) {
    while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY'){
        if (item == parentItem){
            return true;
        }
        item = item.parentNode;
    }
    return false;
}

menuTrigger.addEventListener('click', function() {
    submenu.style.height = '55px';
});

document.querySelector('body').addEventListener('click', function(e) {
    if ( !isChild(e.target, menuTrigger) && !isChild(e.target, submenu) ) {
        submenu.style.height = 0;
    }
});

document.addEventListener('keyup', function(e) {
    if ( e.key == 'Escape' ) {
        submenu.style.height = 0;
    }
});

为什么这不适用于移动设备?我希望在单击菜单项 Behandlinger ( )时将子菜单 ( .behandlinger-meny) 高度设置为。它工作得很好,除了不在菜单项上单击 mobile55px.behandlinger-item


意识到移动菜单有<nav>自己的,这可能会影响事件侦听器。我已经更新了下面的小提琴和简化结构以及核心问题。现在似乎非常接近一个简单的解决方案。

简化结构:

.behandlinger-meny {
    height: 0;
    transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
    overflow: hidden;
}
<div id="wrapper">
  <header>

    <nav class="main-menu">
      <ul>
        <li class="behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav class="mobile-main-menu">
      <ul>
        <li class="mobile-item behandlinger-item"><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

  </header>

  <section> <!-- Separated to follow page scroll -->
    <div id="behandlinger"> <!-- Scroll to position on item click -->
      <nav class="behandlinger-meny">
        <script></script> <!-- Script in question  -->
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>
</div>

可运行版本:

var submenu = document.querySelector('.behandlinger-meny');
var menuTrigger = document.querySelector('.behandlinger-item');

//javascript version of jQuery isChild()
function isChild(item, parentItem) {
    while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY'){
        if (item == parentItem){
            return true;
        }
        item = item.parentNode;
    }
    return false;
}

menuTrigger.addEventListener('click', function() {
    submenu.style.height = '55px';
});

document.querySelector('body').addEventListener('click', function(e) {
    if ( !isChild(e.target, menuTrigger) && !isChild(e.target, submenu) ) {
        submenu.style.height = 0;
    }
});

document.addEventListener('keyup', function(e) {
    if ( e.key == 'Escape' ) {
        submenu.style.height = 0;
    }
});
.behandlinger-meny {
    height: 0;
    transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
    overflow: hidden;
}
<div>
  <header>

    <nav>
      <ul>
        <li><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav>
      <ul>
        <li><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

  </header>

  <section> <!-- Separated to follow page scroll -->
    <div> <!-- Scroll to position on item click -->
      <nav>
        <script></script> <!-- Script in question  -->
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>
</div>

回答

由于您有两个触发器,并且您的事件侦听器仅附加到第一个querySelector触发器,而第二个触发器没有侦听器。

您可以使用querySelectorAllfor 循环中的事件侦听器并将其附加到每个选定的触发器。因为您想要过渡,所以必须使用“max-height”而不是“height”,因为过渡不适用于高度。

为了在点击其他地方(触发器或子菜单除外)时关闭子菜单,我创建了一个函数isRelated()来检查点击目标是触发器本身、子菜单还是两者的子菜单。

具有多个触发器的工作示例(下面的 jQuery 示例):

document.addEventListener('DOMContentLoaded', function() {

  var submenu = document.querySelector('.behandlinger-meny');
  var menuTrigger = document.querySelectorAll('.behandlinger-item');

  function isRelated(item, parentSelector) {
    while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY') {
      parents = document.querySelectorAll(parentSelector);
      for (i = 0; i < parents.length; i++) {
        if (item == parents[i]) {
          return true;
        }
      }
      item = item.parentNode;
    }
    return false;
  }

  for (i = 0; i < menuTrigger.length; i++) {
    menuTrigger[i].addEventListener('click', function() {
      submenu.style.maxHeight = '1000px';
    });
  }

  document.querySelector('body').addEventListener('click', function(e) {
    if (!isRelated(e.target, '.behandlinger-item') && !isRelated(e.target, '.behandlinger-meny')) {
      submenu.style.maxHeight = 0;
    }
  });

  document.addEventListener('keyup', function(e) {
    if (e.key == 'Escape') {
      submenu.style.maxHeight = 0;
    }
  });

});
header {
  display: flex;
}

.behandlinger-meny {
  max-height: 0;
  width: 150px;
  background-color: #ddd;
  transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
  overflow: hidden;
}
header {
  display: flex;
}

.behandlinger-meny {
  max-height: 0;
  width: 150px;
  background-color: #ddd;
  transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
  overflow: hidden;
}
<div>

  <header>
    <nav>
      <ul>
        <li><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav>
      <ul>
        <li><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>
  </header>

  <section>
    <div>
      <nav>
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>

</div>


jQuery 示例:

$().ready(function() {

  var submenu = $('.behandlinger-meny');
  
  $('.behandlinger-item').on('click', function() {
    submenu.css('maxHeight', '1000px');
  });

  $('body').on('click', function(e) {
    if (!$(e.target).parents().is('.behandlinger-item') 
    && !$(e.target).parents().is('.behandlinger-meny')) {
      submenu.css('maxHeight', 0);
    }
  });

  $(document).on('keyup', function(e) {
    if (e.key == 'Escape') {
      submenu.css('maxHeight', 0);
    }
  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div>

  <header>
    <nav>
      <ul>
        <li><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>

    <nav>
      <ul>
        <li><a href="#behandlinger">Behandlinger</a></li>
        <li><a>Item 2</a></li>
        <li><a>Item 3</a></li>
        <li><a>Item 4</a></li>
      </ul>
    </nav>
  </header>

  <section>
    <div>
      <nav>
        <ul>
          <li><a>Sub item 1</a></li>
          <li><a>Sub item 2</a></li>
          <li><a>Sub item 3</a></li>
        </ul>
      </nav>
    </div>
  </section>

  <main>
    …
  </main>

</div>


以上是如何使addEventListener'click'在具有相同类的两个菜单项上工作的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>