Javascript 动态内容事件委托问题

Javascript dynamic content event delegation problem

每次单击按钮时,都会显示一个复选标记。如果单击的按钮未激活,则会删除复选标记。此外,当单击该按钮时,将显示“加载动态内容”按钮。加载动态内容时出现问题。加载后,checkmarks appear.But 删除复选标记不起作用。我对动态内容使用嵌套事件侦听器。当我在加载后检查控制台日志时,按钮 class 元素没有改变。我不知道如何解决这个问题。有什么建议吗?

const checkMarks = document.querySelectorAll('.ck');
// Nested event delegation
document.querySelector('.parent').addEventListener('click', function(e){
  if(e.target.classList.contains('btn-link')){
    // Hide checkmark if not active button
    checkMarks.forEach(function(check, index){
      check.classList.remove('show');
    });
    // Display checkmark
    e.target.closest('div').querySelector('.ck').classList.add('show');
    // Display load dynamic button 
    document.querySelector('.load-content').classList.add('show');
  }
});

document.querySelector('.load-content').addEventListener('click', function(){
    document.querySelector('.parent').innerHTML = '<div><button class="btn-link btn4">Button 4</button><span class="ck">checked</span></div><div><button class="btn-link btn5">Button 5</button><span class="ck">checked</span></div><div><button class="btn-link btn6">Button 6</button><span class="ck">checked</span></div>'
});
.parent{
  padding: 30px;
}
.parent .footer{
  margin-top: 30px;
  margin-bottom: 30px;
  display: flex;
}
.btn-link{
  display: block;
  width: 100px;
  padding: 15px;
  margin-bottom: 15px;
}
.load-content{
  display: none;
  padding: 15px;
}
.load-content.show{
  display: block;
}
.ck{
  display: none;

}
.ck.show{
  display: block;
}
<div class="parent">
<div><button class="btn-link btn1">Button 1</button><span class="ck">checked</span></div>
<div><button class="btn-link btn2">Button 2</button><span class="ck">checked</span></div>
<div><button class="btn-link btn3">Button 3</button><span class="ck">checked</span></div>
</div>
<div class="load"><button class="load-content">Load dynamic content</button></div><div>

jsfiddle

.load-content removes/replaces 节点上的点击处理程序出现在您的代码中并创建新节点。但是这些新节点没有被拾取,因为这个代码:

const checkMarks = document.querySelectorAll('.ck');

只运行一次并选择页面加载时出现的复选标记。尝试在 .parent 单击处理程序中移动此表达式,看看是否有帮助。


理想情况下,您应该在 .load-content 点击处理程序中删除 .parent 上的点击处理程序。这些处理程序仍然存在,这会导致内存泄漏。您应该能够通过将 .parent 的匿名点击处理程序转换为命名函数来解决此问题。然后您可以简单地使用 removeEventListeneraddEventListener 删除并重新添加处理程序。

根据 MDN:Element 方法 querySelectorAll() returns 静态(非实时) NodeList 表示匹配指定选择器组的元素列表。

所以我把它改成了getElementsByClassName,也是循环过程,从forEach到for循环,给你。

const checkMarks = document.getElementsByClassName('ck'); // Changed that

// Nested event delegation
document.querySelector('.parent').addEventListener('click', function(e){
  if(e.target.classList.contains('btn-link')){
    // Hide checkmark if not active button
    for(let i = 0; i < checkMarks.length ; i++){ // Also that changed, as forEach doesn't work for getElementsByClassName.
      checkMarks[i].classList.remove('show');
    };
    // Display checkmark
    e.target.closest('div').querySelector('.ck').classList.add('show');
    // Display load dynamic button 
    document.querySelector('.load-content').classList.add('show');
  }
});

document.querySelector('.load-content').addEventListener('click', function(){
    document.querySelector('.parent').innerHTML = '<div><button class="btn-link btn4">Button 4</button><span class="ck">checked</span></div><div><button class="btn-link btn5">Button 5</button><span class="ck">checked</span></div><div><button class="btn-link btn6">Button 6</button><span class="ck">checked</span></div>'
});
.parent{
  padding: 30px;
}
.parent .footer{
  margin-top: 30px;
  margin-bottom: 30px;
  display: flex;
}
.btn-link{
  display: block;
  width: 100px;
  padding: 15px;
  margin-bottom: 15px;
}
.load-content{
  display: none;
  padding: 15px;
}
.load-content.show{
  display: block;
}
.ck{
  display: none;

}
.ck.show{
  display: block;
}
<div class="parent">
<div><button class="btn-link btn1">Button 1</button><span class="ck">checked</span></div>
<div><button class="btn-link btn2">Button 2</button><span class="ck">checked</span></div>
<div><button class="btn-link btn3">Button 3</button><span class="ck">checked</span></div>
</div>
<div class="load"><button class="load-content">Load dynamic content</button></div><div>