为什么父元素上的 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
一个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