首页 > 解决方案 > 当我单击手风琴标题文本或 V 形图标时,JavaScript 手风琴不起作用

问题描述

我已经构建了一个手风琴,我可以从输入动态添加它,一切正常,除了当我点击手风琴标题文本时它不起作用,而且当我点击右侧的 V 形图标时,我得到一个错误!我不确定为什么会这样。如果我点击一个空白区域,它就可以正常工作而没有任何错误。您可以在 codepen -> https://codepen.io/tauhidul-islam/pen/eYZBzLY上查看演示和代码这里 还有一些屏幕截图,以便您理解。请让我了解发生了什么以及为什么。谢谢你。

const addForm = document.querySelector(".add");
const list = document.querySelector(".section-list");

// Template Generator Function
const generateTemplate = (section) => {
  let html = `
     <div class="accordion">
        <span>${section}</span>
        <i class="fa fa-chevron-down"></i>
     </div>
     <div class="panel">
       <span>Hey there you did it! :-)</span>
     </div>
    `;
  list.innerHTML += html;

  // accordion Selector
  const accordion = document.querySelectorAll(".accordion");

  // Show/Hide accordion Content on Click
  for (i = 0; i < accordion.length; i++) {
    accordion[i].addEventListener("click", (e) => {
      let panel = e.target.nextElementSibling;

      if (panel.classList.contains("panel")) {
        panel.classList.toggle("active");
      }
    });
  }
};

// Add Section
addForm.addEventListener("submit", (e) => {
  e.preventDefault();
  const section = addForm.add.value.trim();
  if (section.length) {
    generateTemplate(section);
    addForm.reset();
  }
});
.container {
  width: 960px;
  margin: auto;
}

.add-input {
  padding: 15px;
  border: 1px solid #dadada;
}

.add-btn {
  background: white;
  padding: 15px 25px;
  margin-bottom: 10px;
  border: 1px solid #dadada;
  cursor: pointer;
}

/* Accordian Panel */

.accordion {
  display: flex;
  justify-content: space-between;
  background: #03a9f4;
  color: white;
  padding: 15px;
  box-shadow: 0px 0px 4px 0px #dadada;
  cursor: pointer;
}

.panel {
  display: none;
  background-color: white;
  padding: 15px;
}

.active {
  display: block;
}
<div class="container">
    <!-- Add Section -->
    <form class="add">
      <input type="text" name="add" class="add-input">
      <button type="submit" class="add-btn">Add Section</button>
    </form>

    <!-- Section List -->
    <div class="section-list"></div>
</div>

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

标签: javascriptdom-eventsaccordion

解决方案


因为您使用e.targetclick是生成的,当您单击文本时div将引用模板,当您单击蓝条时,它不会总是指向同一个元素。相反,您希望始终调用. 这可以通过使用 来完成,但是因为您还使用了箭头函数,绑定将不会正确引用接收事件的元素(),因此如果您更改为使用匿名函数和,它可以工作。spandiv.nextElementSibling.nextElementSiblingdivthis.nextElementSiblingthisdivthis

const addForm = document.querySelector(".add");
const list = document.querySelector(".section-list");

// Template Generator Function
const generateTemplate = (section) => {
  let html = `
     <div class="accordion">
        <span>${section}</span>
        <i class="fa fa-chevron-down">^</i>
     </div>
     <div class="panel">
       <span>Hey there you did it! :-)</span>
     </div>
    `;
  list.innerHTML += html;

  // accordion Selector
  const accordion = document.querySelectorAll(".accordion");

  // Show/Hide accordion Content on Click
  for (i = 0; i < accordion.length; i++) {
    // Use an  anonymous function for the event listener so that 
    // "this" will bind to the element that recieved the event,
    // which is the `div` in this case.
    accordion[i].addEventListener("click", function(e) {
      // We don't want to reference the element that triggered the event
      // because that might be the span or the div and you won't always get
      // the correct reference with .nextElementSibling. We always want to
      // start from the div, which recieves the event.
      let panel = this.nextElementSibling;
      if (panel.classList.contains("panel")) {
        panel.classList.toggle("active");
      }
    });
  }
};

// Add Section
addForm.addEventListener("submit", (e) => {
  e.preventDefault();
  const section = addForm.add.value.trim();
  if (section.length) {
    generateTemplate(section);
    addForm.reset();
  }
});
.container {
  width: 960px;
  margin: auto;
}

.add-input {
  padding: 15px;
  border: 1px solid #dadada;
}

.add-btn {
  background: white;
  padding: 15px 25px;
  margin-bottom: 10px;
  border: 1px solid #dadada;
  cursor: pointer;
}

/* Accordian Panel */

.accordion {
  display: flex;
  justify-content: space-between;
  background: #03a9f4;
  color: white;
  padding: 15px;
  box-shadow: 0px 0px 4px 0px #dadada;
  cursor: pointer;
}

.panel {
  display: none;
  background-color: white;
  padding: 15px;
}

.active {
  display: block;
}
<div class="container">
    <!-- Add Section -->
    <form class="add">
      <input type="text" name="add" class="add-input">
      <button type="submit" class="add-btn">Add Section</button>
    </form>

    <!-- Section List -->
    <div class="section-list"></div>
</div>


推荐阅读