如何创建手风琴以便一次只有 1 个保持打开状态?

How to create accordions so only 1 stays open at a time?

我在 HTML & JS 中使用手风琴时遇到一些困难。我正在尝试对其进行编码,以便一次只打开一个手风琴。如果有人点击并打开一个新的手风琴,所有其他手风琴都应该关闭。这是我的 HTML.

 <div class="accordion">
        <div class="accordion-item">
          <div class="accordion-item-header">
            HUMBER RADIO
          </div>
          <div class="accordion-item-body">
            <div class="accordion-item-body-content">
                <ul>
                    <li><a href="">RADIO NEWS</a></li>
                    <li><a href="">PODCAST</a></li>                 
                    <li><a href="">CONTENT</a></li>                
                </ul>
            </div>
          </div>
        </div>
        </div>
    
        <div class="accordion">
            <div class="accordion-item">
              <div class="accordion-item-header">
                TV NEWS
              </div>
              <div class="accordion-item-body">
                <div class="accordion-item-body-content">
                    <ul>
                        <li><a href="">COVID UPDATES</a></li>
                        <li><a href="">NORTH CAMPUS NEWS</a></li>                 
                        <li><a href="">LAKESHORE CAMPUS NEWS</a></li>                
                    </ul>
                </div>
              </div>
            </div>
            </div>

这是代码的 JavaScript。它可以打开所有这些,但我正在努力对其进行编程,以便其他人关闭。

window.onload = pageReady;

function pageReady() {

    const accordionItemHeaders = document.querySelectorAll(".accordion-item-header");

    accordionItemHeaders.forEach(accordionItemHeader => {
      accordionItemHeader.addEventListener("click", event => {
    
        accordionItemHeader.classList.toggle("active");
        const accordionItemBody = accordionItemHeader.nextElementSibling;
        if(accordionItemHeader.classList.contains("active")) {
          accordionItemBody.style.maxHeight = "100px";
        }
        else {
          accordionItemBody.style.maxHeight = "0px";
        }
        
      });
    });
}

几个调整:

  1. 在将当前点击的 header 设置为 .active 之前,我们 select 之前激活的 header(如果存在)并删除 class.

  2. 不是使用 JavaScript 设置内联样式,这里是使用 CSS 设置 max-height 的更简洁的替代方法,使用 adjacent sibling combinator(a加号)到 select 活动手风琴 header 之后的手风琴 body。

const accordionItemHeaders = document.querySelectorAll(".accordion-item-header");

accordionItemHeaders.forEach(accordionItemHeader => {
  accordionItemHeader.addEventListener("click", event => {
    if (accordionItemHeader.classList.contains('active')) {
      accordionItemHeader.classList.remove("active");
    } else {
      document.querySelector(".accordion-item-header.active")?.classList.remove("active");
      accordionItemHeader.classList.add("active");
    }
  });
});
.accordion-item-header.active+.accordion-item-body {
  max-height: 100px;
}

类似,我们将让CSS处理样式,只使用javascript来操纵类。

主要区别在于我们将容纳多个手风琴组并利用事件冒泡。事件侦听器将附加到手风琴组,然后检查事件目标。如果您最终使用 JS 向手风琴中注入更多元素,这也很方便。

//Get the Accordion Groups
const accordions = document.querySelectorAll(".accordion");


accordions.forEach(accordion => {
  //Add event listener to each ACCORDION , use function not fat arrow to get access to "this"
  accordion.addEventListener("click", function(event) {
    //Check the event targe is an item header
    if (event.target.matches(".accordion-item-header")) {
      //Get current active, here "this" refers to the accordion group clicked on
      let active = this.querySelector(".active");
      
      //Toggle element if active element clicked
      if (active == event.target) {
        event.target.classList.toggle("active");
      } else {
        //Remove current active.
        if (active) {
          active.classList.remove("active");
        }
        //Add active        
        event.target.classList.add("active");
      }
    }
  });
});
.accordion {
  width: 45%;
  display: inline-block;
  vertical-align: top;
}

.accordion .accordion-item-header+.accordion-item-body {
  max-height: 0px;
  overflow: hidden;
  transition: all 0.5s;
}

.accordion .accordion-item-header.active+.accordion-item-body {
  max-height: 100px;
}
<div class="accordion">
  <h2>Accordion Group 1</h2>
  <div class="accordion-item">
    <div class="accordion-item-header">
      HUMBER RADIO
    </div>
    <div class="accordion-item-body">
      <div class="accordion-item-body-content">
        <ul>
          <li><a href="">RADIO NEWS</a></li>
          <li><a href="">PODCAST</a></li>
          <li><a href="">CONTENT</a></li>
        </ul>
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <div class="accordion-item-header">
      TV NEWS
    </div>
    <div class="accordion-item-body">
      <div class="accordion-item-body-content">
        <ul>
          <li><a href="">COVID UPDATES</a></li>
          <li><a href="">NORTH CAMPUS NEWS</a></li>
          <li><a href="">LAKESHORE CAMPUS NEWS</a></li>
        </ul>
      </div>
    </div>
  </div>
</div>

<div class="accordion">
  <h2>Accordion Group 1</h2>
  <div class="accordion-item">
    <div class="accordion-item-header">
      JJJ RADIO
    </div>
    <div class="accordion-item-body">
      <div class="accordion-item-body-content">
        <ul>
          <li><a href="">RADIO NEWS</a></li>
          <li><a href="">PODCAST</a></li>
          <li><a href="">CONTENT</a></li>
        </ul>
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <div class="accordion-item-header">
      Radio NEWS
    </div>
    <div class="accordion-item-body">
      <div class="accordion-item-body-content">
        <ul>
          <li><a href="">COVID UPDATES</a></li>
          <li><a href="">NORTH CAMPUS NEWS</a></li>
          <li><a href="">LAKESHORE CAMPUS NEWS</a></li>
        </ul>
      </div>
    </div>
  </div>
</div>