仅向单击的手风琴面板添加或删除 class

Add or remove class only to the accordion panel that got clicked

我需要一些帮助来修复手风琴组件中的错误:

  1. 在我下面的示例中,请单击面板 1 打开并再次单击面板 1 将其关闭。
  2. 然后点击面板 2。您会看到面板 1 和面板 2 同时激活了 class,这是错误的。 class 活动应该只添加或删除到被点击的手风琴面板。

请注意,我需要保留相同的功能,即当另一个面板打开时手风琴面板会折叠。

非常感谢您的帮助和指导。 谢谢。

var acc = document.getElementsByClassName("accordion");
var i;
var prevExpandedPanel = null;
for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    if (prevExpandedPanel && this !== prevExpandedPanel) {  
      prevExpandedPanel.classList.toggle("active");
      prevExpandedPanel.nextElementSibling.style.maxHeight = null;
    }
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    } 
    prevExpandedPanel = this;
  });
}
.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}

.active, .accordion:hover {
  background-color: #f8f8f8;
}

.accordion:after {
  content: '[=12=]2B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "12";
}

.panel {
  padding: 0 18px;
  background-color: white;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}
<button class="accordion">Panel 1</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 2</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 3</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

您正在混合 this 的引用,但这样分配它。

试试这个:

let acc = document.querySelectorAll('.accordion');
for (let i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function() {
    for (let index = 0; index < acc.length; index++) {
      const el = acc[index];
      if (this !== el) {
        el.classList.remove('active');
        el.nextElementSibling.style.maxHeight = null;
      }
    }
    this.classList.toggle("active");
    let panel = this.nextElementSibling;
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    } 
  });
}
.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}

.active, .accordion:hover {
  background-color: #f8f8f8;
}

.accordion:after {
  content: '[=11=]2B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "12";
}

.panel {
  padding: 0 18px;
  background-color: white;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}
<button class="accordion">Panel 1</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 2</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 3</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

您需要用 div:

包裹手风琴
<div class="accordion">
  <button class="button">Panel 1</button>
  <div class="panel">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
  </div>
</div>

<div class="accordion">
  <button class="button">Panel 2</button>
  <div class="panel">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
  </div>
</div>

<div class="accordion">
  <button class="button">Panel 3</button>
  <div class="panel">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
  </div>
</div>

之后只需尝试以下代码:

const resetCurrentActiveAccordion = (active) => {
    if(!active) return
  const buttonParent = active.closest('.accordion')
  const panel = buttonParent.querySelector('.panel')
  active.classList.remove('active')
  panel.style.maxHeight = null
}

const handleAccordionClick = event => {
    const parent = event.target.closest('.accordion')
  const panel = parent.querySelector('.panel')
  const active = document.querySelector('.active')
  
  resetCurrentActiveAccordion(active)
  if(active === event.target) return
  
  event.target.classList.add('active')
  panel.style.maxHeight = `${panel.scrollHeight}px`;
}

const initializeAccordion = () => {
  const accordions = document.querySelectorAll('.accordion')
  accordions.forEach(accordion => {
    const button = accordion.querySelector('.button')
    const panel = accordion.querySelector('.panel')
    button.addEventListener('click', handleAccordionClick)
  })
}

initializeAccordion()

当然,还要更新您的样式:

.button {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}

.active, .button:hover {
  background-color: #f8f8f8;
}

.button:after {
  content: '[=12=]2B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "12";
}

.panel {
  padding: 0 18px;
  background-color: white;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}

代码片段link:https://jsfiddle.net/j9k8hdzb/

无需记住之前选择的元素即可:

var acc = document.getElementsByClassName("accordion");

for (var i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function(e) {
    let active = this.classList.contains('active');
    let panel = this.nextElementSibling;
    
    [...acc].forEach(function(item) {
      item.classList.remove('active');
      item.nextElementSibling.style.maxHeight = null;
    });
    
    if(!active) {
      this.classList.add('active');
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
  });
}
.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}

.active, .accordion:hover {
  background-color: #f8f8f8;
}

.accordion:after {
  content: '[=11=]2B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "12";
}

.panel {
  padding: 0 18px;
  background-color: white;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}
<button class="accordion">Panel 1</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 2</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 3</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

可能的解决方案如下:

const accordionButtons = document.querySelectorAll(".accordion");

/* 
 * create an array of object associating the `button.accordion`
 * with the corresponding `div.panel`
 * (this is not strictly necessary, I just find it convenient)
 */
const accordions = []
accordionButtons.forEach(button => {
  accordions.push({
    btnEl: button,
    panelEl: button.nextElementSibling
  })
});

/*
 * create a function to handle the accordions toggle
 */
function expandSingle(accordion) {
  const isExpanded = accordion.btnEl.classList.contains('active');
  
  // 1. remove the active class from all accordions
  //    and set the max-height of all panels to 0
  accordions.forEach(item => {
    item.btnEl.classList.remove('active');
    item.panelEl.style.maxHeight = 0;
  });
  
  // 2. if the selected accordion was not already active/expanded
  //    add the active class to it and set the max-height
  if (!isExpanded) {
    accordion.btnEl.classList.add('active');
    accordion.panelEl.style.maxHeight = accordion.panelEl.scrollHeight + 'px';
  }
}

/*
 * add an event listener to each `button.accordion`, calling the function
 * which handles the accordions toggle
 */
accordions.forEach(accordion => {
  accordion.btnEl.addEventListener('click', () => expandSingle(accordion))
})
.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}

.active, .accordion:hover {
  background-color: #f8f8f8;
}

.accordion:after {
  content: '[=11=]2B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "12";
}

.panel {
  padding: 0 18px;
  background-color: white;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}
<button class="accordion">Panel 1</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 2</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>

<button class="accordion">Panel 3</button>
<div class="panel">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>