为什么事件处理程序只在第一个项目元素处切换 class 名称而不是其余的?

Why does the event handler toggle the class name just at the first item element but not for the rest?

我看到 class 被主动添加到第一个元素的控制台中,但仅限于第一个元素。事件侦听器绑定到 svg 按钮。 Class 'open' 把 'hidden-block' display 变成 display: block;在项目容器中

const faqDropDown = document.querySelector(".accordion-icon");
const faqContainer = document.querySelector(".item");

faqDropDown.addEventListener("click", function() {
  faqContainer.classList.toggle("open");
});
.item { margin-bottom: 10px; }
p { margin: 0; }
svg { width 1em; height: 1em; margin: 10px; }
<div class="item">
  <p class="number">01</p>
  <p class="text">lorem ipsum ist?</p>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    class="accordion-icon"
    fill="none"
    viewBox="0 0 24 24"
    stroke="currentColor"
  >
    <path
      stroke-linecap="round"
      stroke-linejoin="round"
      stroke-width="2"
      d="M19 9l-7 7-7-7"
    />
  </svg>

  <div class="hidden-box">
    <p>
      Lorem ipsum, dolor sit amet consectetur adipisicing elit.
      Et, tempore repudiandae. Minima, cupiditate totam nihil
      laborum rem sit, est, ea et quaerat hic accusantium quos.
    </p>
  </div>
</div>

<div class="item">
  <p class="number">02</p>
  <p class="text">lorem ipsum ist?</p>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    class="accordion-icon"
    fill="none"
    viewBox="0 0 24 24"
    stroke="currentColor"
  >
    <path
      stroke-linecap="round"
      stroke-linejoin="round"
      stroke-width="2"
      d="M19 9l-7 7-7-7"
    />
  </svg>

  <div class="hidden-box">
    <p>
      Lorem ipsum, dolor sit amet consectetur adipisicing elit.
      Et, tempore repudiandae. Minima, cupiditate totam nihil
      laborum rem sit, est, ea et quaerat hic accusantium quos.
    </p>
  </div>
</div>

你的问题是你正在使用 querySelector 它将 return 它遇到的第一个对象,这意味着它将 return 只有第一个项目 .item.

为了对带有 class 的多个项目应用一些更改(我想你有多个 class="item"),你需要使用 querySelectorAll,这将 return具有 class item.

的节点数组

下面我给你留下了一个例子,说明如何使用 querySelectorAll 然后遍历每个节点,然后应用你想要的更改。

注意:如果您查看代码,html 是我制作的,只是为了证明它有效(它将所有项目更改为红色)。 javascript 部分是更改为对所有项目进行正确更改的部分。只需将其复制粘贴到您的代码中即可。

const faqDropDown = document.querySelector(".accordion-icon");
const faqContainers = document.querySelectorAll(".item");

faqDropDown.addEventListener("click", function() {
  faqContainers.forEach(faqContainer => {
    faqContainer.classList.toggle("open");
  })
});
.open {
  color: red;
}
<button class="accordion-icon">
toggle open
</button>

<div class="item">
  item1
</div>

<div class="item">
  item2
</div>

<div class="item">
  item3
</div>

<div class="item">
  item4
</div>

OP 需要处理手风琴所有项目的状态。因此,对于提供的示例,必须为每个项目的 svg 图标注册一个事件处理程序。

处理程序不仅需要处理项目的切换状态,还需要检测和处理关闭所有其他项目的情况...

function handleAccordionItemStates({ currentTarget }) {
  const currentItem = currentTarget.closest('.item');
  const currentAccordion = currentItem.closest('.accordion');

  const isCloseOthers = !currentItem.classList.contains('open');
  if (isCloseOthers) {

    currentAccordion
      .querySelectorAll('.item')
      .forEach(item => {
        if (item !== currentItem) {
          item.classList.remove('open');
        }
      });
  }
  currentItem.classList.toggle('open');
}

function init() {
  document
    .querySelectorAll('.accordion-icon')
    .forEach(elmNode =>
      elmNode.addEventListener('click', handleAccordionItemStates)
    );
}
init();
p { margin: 0; }
svg {
  width 1em;
  height: 1em;
  transition: transform .3s ease-in;
}

.item { margin-bottom: 10px; }
.item p { float: left; margin-right: 10px; }
.item svg { float: right; margin-right: 50px; }

.hidden-box {
  clear: both;
  overflow: hidden;
  padding-top: 5px;
  transition: max-height .6s ease-in-out;
  max-height: 0;
}
.item.open .hidden-box { max-height: 900px; }
.item.open svg { transform: rotate(180deg); }
<div class="accordion">
  <div class="item">
    <p class="number">01</p>
    <p class="text">lorem ipsum</p>
    <svg
      xmlns="http://www.w3.org/2000/svg"
      class="accordion-icon"
      fill="none"
      viewBox="0 0 24 24"
      stroke="currentColor"
    >
      <path
        stroke-linecap="round"
        stroke-linejoin="round"
        stroke-width="2"
        d="M19 9l-7 7-7-7"
      />
    </svg>

    <div class="hidden-box">
      <p>
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Et,
        tempore repudiandae. Minima, cupiditate totam nihil laborum rem sit,
        est, ea et quaerat hic accusantium quos.
      </p>
    </div>
  </div>

  <div class="item">
    <p class="number">02</p>
    <p class="text">accusantium quos</p>
    <svg
      xmlns="http://www.w3.org/2000/svg"
      class="accordion-icon"
      fill="none"
      viewBox="0 0 24 24"
      stroke="currentColor"
    >
      <path
        stroke-linecap="round"
        stroke-linejoin="round"
        stroke-width="2"
        d="M19 9l-7 7-7-7"
      />
    </svg>

    <div class="hidden-box">
      <p>
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Et,
        tempore repudiandae. Minima, cupiditate totam nihil laborum rem sit,
        est, ea et quaerat hic accusantium quos.
      </p>
    </div>
  </div>

  <div class="item">
    <p class="number">03</p>
    <p class="text">cupiditate totam</p>
    <svg
      xmlns="http://www.w3.org/2000/svg"
      class="accordion-icon"
      fill="none"
      viewBox="0 0 24 24"
      stroke="currentColor"
    >
      <path
        stroke-linecap="round"
        stroke-linejoin="round"
        stroke-width="2"
        d="M19 9l-7 7-7-7"
      />
    </svg>

    <div class="hidden-box">
      <p>
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Et,
        tempore repudiandae. Minima, cupiditate totam nihil laborum rem sit,
        est, ea et quaerat hic accusantium quos.
      </p>
    </div>
  </div>

</div>