简单香草 javascript 手风琴 - 单击活动项目时出现问题

Simple vanilla javascript accordion - problem when click on active item

我的手风琴脚本有问题。

谁能解释一下 - 为什么在点击 活动项目 后,动画不像点击下一个项目时那样执行?

我觉得问题出在if条件的开头:

if (this.nextElementSibling.style.maxHeight) {

当我点击 accordionItemHead

let accordions = document.querySelectorAll('.js-accordions');

accordions.forEach(function(accordion) {

  let singleAccordionItems = accordion.querySelectorAll('.js-accordions-item');

  singleAccordionItems.forEach(function(accordionItem) {

    let accordionItemHead = accordionItem.querySelector('.js-accordions-head');
    let accordionItemContent = accordionItem.querySelector('.js-accordions-content');

    accordionItemHead.addEventListener("click", function() {

      if (this.nextElementSibling.style.maxHeight) {
        this.nextElementSibling.style.maxHeight = null;

      } else {

        singleAccordionItems.forEach(function(item) {

          item.querySelector('.js-accordions-content').style.maxHeight = null;
          item.classList.remove('is-active');

        });
      }

      accordionItemContent.style.maxHeight = accordionItemContent.scrollHeight + "px";
      accordionItem.classList.toggle('is-active');

    });


  });

});
.c-accordion {
  box-shadow: 2px 2px 24px rgba(0, 0, 0, 0.05);
}

.c-accordion__item {
  padding-left: 20px;
}

.c-accordion__header {
  position: relative;
  cursor: pointer;
  padding: 26px 0 22px;
}

.c-accordion__header::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background-color: blue;
}

.c-accordion__item:first-child .c-accordion__header::before {
  content: none;
}

.c-accordion__header h4 {
  padding-right: 60px;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.2;
}

.c-accordion__text {
  max-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition-duration: 400ms;
  transition-property: max-height, visibility;
  transition-delay: 0, 400ms;
}

.is-active .c-accordion__text {
  visibility: visible;
  transition-duration: 400ms;
  transition-property: max-height, visibility;
  transition-delay: 400ms, 0;
}

.c-accordion__text p {
  margin-top: 0;
  margin-bottom: 25px;
}

.c-accordion__text-inner {
  display: flex;
  flex-direction: column;
}

.c-accordion__icon {
  position: absolute;
  top: 50%;
  margin-top: -9px;
  right: 25px;
  font-size: 18px;
  color: red;
}

.c-accordion__icon::after {
  position: absolute;
  top: 50%;
  margin-top: -1px;
  left: 0;
  content: '';
  width: 19px;
  height: 2px;
  background-color: blue;
  transform: scalex(0);
  transition: transform 0.4s;
}

.is-active .c-accordion__icon::after {
  transform: scaleX(1);
}

.c-accordion__icon::before {
  display: inline-block;
  transition: transform 0.3s, opacity 0.5s;
}

.is-active .c-accordion__icon::before {
  transform: rotate(90deg);
  opacity: 0;
}
<div class="c-accordion js-accordions">
  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content" style="">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 2</p>
      </div>
    </div>

  </div>

  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
      </div>
    </div>

  </div>

  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
      </div>
    </div>

  </div>

  <div class="c-accordion__item js-accordions-item">

    <div class="c-accordion__header js-accordions-head">
      <h4>Długie pytanie w dwóch linijkach</h4>
      <span class="c-accordion__icon icon icon-plus"></span>
    </div>

    <div class="c-accordion__text js-accordions-content">
      <div class="c-accordion__text-inner">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Consectetur adipiscing elit.
          Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
      </div>
    </div>
  </div>
</div>

我认为这是因为您正在尝试使用 css 和 javascript 来控制动画。
您可以做的一件事是为两个状态都设置一个 css 类 active 和 no-active,然后您使用 Js 在它们之间切换。

.no-active {
max-height: 0px
}
.no-active {
max-height: 9999px
}

只需对条件进行一点改动就可以正常工作(出于某种原因,我投了反对票,所以我发布了整个代码):

      let accordions = document.querySelectorAll(".js-accordions");

      accordions.forEach(function (accordion) {
        let singleAccordionItems = accordion.querySelectorAll(".js-accordions-item");

        singleAccordionItems.forEach(function (accordionItem) {
          let accordionItemHead = accordionItem.querySelector(".js-accordions-head");
          let accordionItemContent = accordionItem.querySelector(".js-accordions-content");

          accordionItemHead.addEventListener("click", function () {
            if (this.nextElementSibling.style.maxHeight) {
              this.nextElementSibling.style.maxHeight = null;
            } else {
              singleAccordionItems.forEach(function (item) {
                item.querySelector(".js-accordions-content").style.maxHeight = null;
                item.classList.remove("is-active");
              });
              accordionItemContent.style.maxHeight = accordionItemContent.scrollHeight + "px";
              accordionItem.classList.toggle("is-active");
            }
          });
        });
      });
     .c-accordion {
        box-shadow: 2px 2px 24px rgba(0, 0, 0, 0.05);
      }

      .c-accordion__item {
        padding-left: 20px;
      }

      .c-accordion__header {
        position: relative;
        cursor: pointer;
        padding: 26px 0 22px;
      }

      .c-accordion__header::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 1px;
        background-color: blue;
      }

      .c-accordion__item:first-child .c-accordion__header::before {
        content: none;
      }

      .c-accordion__header h4 {
        padding-right: 60px;
        font-size: 18px;
        font-weight: 500;
        line-height: 1.2;
      }

      .c-accordion__text {
        max-height: 0;
        overflow: hidden;
        visibility: hidden;
        transition-duration: 400ms;
        transition-property: max-height, visibility;
        transition-delay: 0, 400ms;
      }

      .is-active .c-accordion__text {
        visibility: visible;
        transition-duration: 400ms;
        transition-property: max-height, visibility;
        transition-delay: 400ms, 0;
      }

      .c-accordion__text p {
        margin-top: 0;
        margin-bottom: 25px;
      }

      .c-accordion__text-inner {
        display: flex;
        flex-direction: column;
      }

      .c-accordion__icon {
        position: absolute;
        top: 50%;
        margin-top: -9px;
        right: 25px;
        font-size: 18px;
        color: red;
      }

      .c-accordion__icon::after {
        position: absolute;
        top: 50%;
        margin-top: -1px;
        left: 0;
        content: "";
        width: 19px;
        height: 2px;
        background-color: blue;
        transform: scalex(0);
        transition: transform 0.4s;
      }

      .is-active .c-accordion__icon::after {
        transform: scaleX(1);
      }

      .c-accordion__icon::before {
        display: inline-block;
        transition: transform 0.3s, opacity 0.5s;
      }

      .is-active .c-accordion__icon::before {
        transform: rotate(90deg);
        opacity: 0;
      }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <div class="c-accordion js-accordions">
      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content" style="">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 2
            </p>
          </div>
        </div>
      </div>

      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
            </p>
          </div>
        </div>
      </div>

      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
            </p>
          </div>
        </div>
      </div>

      <div class="c-accordion__item js-accordions-item">
        <div class="c-accordion__header js-accordions-head">
          <h4>Długie pytanie w dwóch linijkach</h4>
          <span class="c-accordion__icon icon icon-plus"></span>
        </div>

        <div class="c-accordion__text js-accordions-content">
          <div class="c-accordion__text-inner">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac
              aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
              himenaeos. Consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
              Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
            </p>
          </div>
        </div>
      </div>
    </div>

更正后的 JS 代码:

let accordions = document.querySelectorAll('.js-accordions');

accordions.forEach(function (accordion) {

    let singleAccordionItems = accordion.querySelectorAll('.js-accordions-item');

    singleAccordionItems.forEach(function (accordionItem) {

        let accordionItemHead = accordionItem.querySelector('.js-accordions-head');
        let accordionItemContent = accordionItem.querySelector('.js-accordions-content');

        accordionItemHead.addEventListener("click", function() {

            if (this.nextElementSibling.style.maxHeight) {
                this.nextElementSibling.style.maxHeight = null;
                accordionItem.classList.remove('is-active');

            } else {

                singleAccordionItems.forEach(function (item) {

                    item.querySelector('.js-accordions-content').style.maxHeight = null;
                    item.classList.remove('is-active');

                });

                accordionItemContent.style.maxHeight = accordionItemContent.scrollHeight + "px";
                accordionItem.classList.toggle('is-active');
            }
            
        });
        
    
    });
    
});