为什么父元素上的 preventDefault 在单击时禁用以编程方式检查子复选框?

Why does preventDefault on parent element disable programmatically checking child checkbox on click?

一个div元素的点击事件以e.preventDefault()开头。这使得手动单击复选框 input 或其关联的 label 不再有效。

在更多 JavaScript 代码的帮助下,手动单击 label 会生成预期结果,因为该复选框现在以编程方式 checked/unchecked.

但是,尽管以编程方式 checking/unchecking 实现了类似的 JavaScript 代码,但手动单击复选框 input 仍然不起作用。为什么?

document.querySelector('div').onclick = function (e)
{
      e.preventDefault();
      if (e.target.tagName.toUpperCase() == 'LABEL')
      {
          e.target.previousElementSibling.checked = !e.target.previousElementSibling.checked;
      }
      else if (e.target.tagName.toUpperCase() == 'INPUT')
      {
          e.target.checked = !e.target.checked;
      }
}
<div>
      <input  id="check" type="checkbox">
      <label for="check">Label Text</label>
</div>

单击 label 会按预期设置 checked 属性,因为没有与要取消的标签相关的 default 操作。单击 input 会按预期设置 属性,但由于默认操作(切换选中的 属性)被阻止,它会恢复到之前的状态。

请参阅: 了解更深入的讨论。

document.querySelector('div').onclick = function (e)
{
      e.preventDefault();
      if (e.target.tagName.toUpperCase() == 'LABEL')
      {
          e.target.previousElementSibling.checked = !e.target.previousElementSibling.checked;
      }
      else if (e.target.tagName.toUpperCase() == 'INPUT')
      {
      console.clear();
      console.log(e.target.checked);
          e.target.checked = !e.target.checked;
      console.log(e.target.checked);
}
}
<div>
      <input  id="check" type="checkbox">
      <label for="check">Label Text</label>
</div>

编辑

针对您的评论,我认为最干净的解决方案是明确地将侦听器应用于您想要控制的那些元素,而不是在提供的 API 方法上调用 stopPropagation() 以避免触发家长听众。

然后您可以处理您需要的任何逻辑,而无需处理外部方法的工件。如果您还需要父级监听 运行,您可以在控制逻辑完成后以编程方式激活它。

// original API listener
document.querySelector('.container').addEventListener('click', function (e) {
  e.preventDefault();
  
  // add container specific code
  console.log('clicked div');
 
});

// your isolated listener
document.querySelector('.checkbox-container').addEventListener('click', function (e) {
  e.stopPropagation(); // stop the event from propagating to the parent listener
  
  // add checkbox specific code 
  console.clear();
  console.log('clicked checkbox container');
  
  // even programmatically 'clicking' parent if you need to
  e.currentTarget.parentElement.click();
});
.container {
  width: 150px;
  height: 60px;
  background-color: lightgray;
}

.checkbox-container {
  display: inline-block;
  background-color: aquamarine;
}
<div class="container">
  <div class="checkbox-container">
    <input id="check" type="checkbox">
    <label for="check" >Label Text</label>
  </div>
</div>

防止默认传播经常向下传播到 child。有一种方法可以通过使用 event.stopPropagation 来阻止这种情况的发生。阅读此处,详细了解可能对您的事业有所帮助的其他有用方法。

https://chunkybyte.medium.com/the-one-with-event-propagation-and-e-preventdefault-part-1-6d84f3c4220