JavaScript 当我点击手风琴标题文本或人字形图标时,手风琴不工作

JavaScript Accordion not working when i click on accordion heading text or chevron icon

我已经构建了一个手风琴,我可以从输入中动态添加它并且一切正常,除了当我点击手风琴标题文本时它不起作用,而且当我点击右侧的 V 形图标时我得到一个错误!!我不确定为什么会这样。如果我点击一个空的 space 区域,它就可以正常工作,没有任何错误。您可以在 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>

因为您在生成的 divclick 事件中使用 e.target,当您单击文本和 div 当你点击蓝色条时,所以 .nextElementSibling 不会总是指向同一个元素。相反,您希望始终在 div 上调用 .nextElementSibling。这可以通过使用 this.nextElementSibling 来完成,但是因为您还使用了箭头函数,所以 this 绑定将无法正确引用接收事件的元素(div),所以如果你改为使用匿名函数 this,它起作用了。

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>

没有用于分配点击处理程序的循环:

const addForm = document.querySelector(".add");
const list = document.querySelector(".section-list");
const expand = (element) => {
  let panel = element.nextElementSibling;
  if (panel.classList.contains("panel")) {
    panel.classList.toggle("active");
  }
};


// Template Generator Function
const getAccordionItem = (section) => {
  let html = `
      <div class="accordion" onclick="expand(this)">
                <span>${section}</span>
                <i class="fa fa-chevron-down"></i>
            </div>
            <div class="panel">
                <span>Hey there you did it! :-)</span>
            </div>
    `;
  return html;
};

// Add Section
addForm.addEventListener("submit", (e) => {
  e.preventDefault();
  const section = addForm.add.value.trim();
  if (section.length) {
      list.innerHTML += getAccordionItem(section);
    addForm.reset();
  }
});
body {
  margin: 50px 0;
  background-color: #f2f2f2;
  font-family: Arial, Helvetica, sans-serif;
}

.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;
}
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Dynamic Accordian</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css">
  <link rel="stylesheet" href="css/style.css">
</head>

<body>

  <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>

  <script src="app.js"></script>
</body>

</html>