我有一些元素(例如带有.label类的div),其中每个元素都有单选按钮。当用户单击此“标签”时,我以编程方式将其设置为选中状态。但是,如果我对点击事件使用了preventDefault(),那么如果用户恰好在广播上单击,则不会选择广播。
请帮助我了解这种奇怪的行为。 我知道解决方案,我知道为什么父元素上的preventDefault()不允许检查单选,但我想理解,为什么单选上的click事件可以不允许以编程方式设置其状态。您会看到单击单选按钮会显示已选中单选,但未选中。
$(function () {
$('.label').on('click', function(e) {
var $radio = $(this).find(':radio')
console.log('before prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`);
e.preventDefault();
if (!$(this).hasClass('checked')) {
$('.checked').removeClass('checked');
$(this).addClass('checked');
}
$radio.prop('checked', true);
console.log('after prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`);
setTimeout(function () {
console.log('after timeout', `checked=${$radio.prop('checked')}`);
}, 500);
});
$(':radio').on('click', function (e) {
console.log('click', `prevented=${e.isDefaultPrevented()}`);
});
});
.label {
padding: 10px;
margin-bottom: 10px;
border: 1px solid #000;
}
.label.checked {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="label">
Label 1 <input type="radio" name="radio" value="1">
</div>
<div class="label">
Label 2 <input type="radio" name="radio" value="2">
</div>
更新。我如何看待这种情况:
.label
上触发cancelled
标志。div
现在以编程方式获取类“ .checked”并再次将单选设置为被选中。我对吗?
答案 0 :(得分:2)
我如何看待这种情况(受https://stackoverflow.com/a/15767580/11357125的启发):
<input>
<div>
上进行处理。事件侦听器调用preventDefault
方法,并设置内部cancelled
标志。 <div>
将类“ .checked”和广播设置为现在已通过编程方式再次进行检查。答案 1 :(得分:1)
在父元素上使用preventDefault()可以防止触发原始事件,但不会停止传播。了解层次结构和事件传播至关重要。
您的代码段中包含解决方案的一部分。如果您注释掉该特定行,则代码可以正常工作,就像您期望的那样。 但是,如果您使用
e.stopPropagation();
它也可以工作。
为了不重复已有的信息,我在这里(Why does preventDefault() on a parent element's click 'disable' a checkbox?)发现了一个非常相似的案例,它可以帮助您更好地了解事件传播和冒泡。
您还可以在这里找到更好的解释(https://medium.freecodecamp.org/a-simplified-explanation-of-event-propagation-in-javascript-f9de7961a06e)。
MDN文档也很少给人留下深刻的印象(https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)。
答案 2 :(得分:0)
您只需要添加e.stopPropagation()
即可再次返回单选按钮的默认功能,即checked
该行为是,您有radio
是div
的子代,而您的click
侦听器是基于父级div
以及您preventDefault
然后孩子们也继承了预防措施。
检查that
如果在一个元素上按下按钮,然后在另一个元素上释放按钮,则会在包含这两个元素的最特定祖先元素上触发该事件。