提问人:Fabrício Matté 提问时间:2/25/2014 最后编辑:Brian Tompsett - 汤莱恩Fabrício Matté 更新时间:8/29/2020 访问量:1261
为什么在调用 event.preventDefault() 后使用 JavaScript 切换复选框/单选按钮会失败?
Why does toggling a checkbox/radiobutton with JavaScript fail after calling event.preventDefault()?
问:
请考虑以下示例代码:
<span>
<input type="checkbox">
</span>
$('span').click(function(e) {
e.preventDefault();
$(':checkbox')[0].checked = true;
});
据我所知,这应该发生:
preventDefault()
应防止浏览器的默认行为选中该复选框,即使事件处理程序附加在 DOM 层次结构的上方。这部分工作正常。- 我认为,设置应该可以工作,因为它应该独立于浏览器对我取消的事件的默认操作。这部分似乎有问题,好像影响了它 - 删除它,它按预期工作。
.checked = true
preventDefault()
preventDefault()
复选框始终处于未选中状态的真正原因是什么?
我已经在 Chrome 33 和 Firefox 27 上进行了测试,所以这似乎不是浏览器错误。
这个问题主要是出于好奇心,想扩展我的 DOM/事件模型知识。我不想要解决方法,而是想知道为什么这个例子失败了。
答:
您必须同时将 和 并设置选中preventDefault
click
mouseup
mouseup
尝试:
$('span').click(function(e) {
e.preventDefault();
}).mouseup(function(e){
e.preventDefault();
$(':checkbox')[0].checked = true;
});
评论
preventDefault
span's
input
mouseup
click
preventDefault
mouseup
click
给定您的 HTML:
<span>
<input type="checkbox">
</span>
和你的代码:
$('span').click(function(e) {
e.preventDefault();
$(':checkbox')[0].checked = true;
});
事件冒泡是你在这里的问题。
单击 时,单击事件将传播到 . 是对从 传播的事件对象的调用。checkbox
span
e.preventDefault()
checkbox
因此,是针对自身执行的,防止它被检查。preventDefault()
checkbox
通过它“取消”的点击事件将保持取消状态,直到事件流完成。(有关更多详细信息,请参阅答案底部)checkbox
preventDefault
如果对跨度应用一些样式,您会注意到单击代码会按预期工作,但由于上述原因,单击代码本身会复制您的问题。checkbox
checkbox
演示 - 原始小提琴 + 样式。点击是好的,不是span
checkbox
根据 preventDefault() 上的 MDN 文档:
在事件流的任何阶段调用都会取消 事件,这意味着通常由 由于该事件,不会发生实施。
preventDefault
DOM Level 2 规范还指出:
如果事件是可取消的,则该方法用于 表示要取消事件,表示任何默认操作 通常由实施所采取的作为事件的结果不会 发生。如果在事件流的任何阶段,preventDefault 方法 称为事件被取消。
preventDefault
示例 5 下的 DOM Level 3 事件规范说明:
与元素上的事件关联的默认操作将切换该元素的 IDL 属性值。如果事件的默认操作被取消,则该值将恢复到其以前的状态。
click
<input type="checkbox">
checked
click
评论
click
span
preventDefault()
the line of code which sets the checked state does not work
preventDefault
.checked = true
The misunderstanding probably occurs because you are thinking of the event as firing after the actual click has been fully processed (i.e. the checkbox has been toggled) while in reality the event model stipulates that the handler fires while the event is being processed.
By the time your line of code executes the event chain is still active and the instructions to prevent the default behaviour are too
这是我所感受到的预期行为,因为当您说 event.preventDefault() 时,您是在指示浏览器在此事件中不要对其执行任何操作。因此,即使在语句之后,当您明确选中复选框时,浏览器也不会对其执行任何操作。 当我更改事件时,我们可以看到差异如下:
$('span').click(function(e) {
e.preventDefault();
//$(':checkbox')[0].checked = true;
setTimeout(function(){$(':checkbox')[0].checked = true;});
});
使用超时,我们正在更改事件外部的 checked 属性,因此它被检查。
将部分代码包装在 a 中就可以了,正如你在这里看到的 http://jsfiddle.net/y7C77/setTimeout
$('span').click(function(e) {
e.preventDefault();
setTimeout(function () {
$('input').prop('checked', true);
}, 1);
});
preventDefault()
取消默认操作,我认为即使您手动执行浏览器会执行的操作(在本例中:更改属性),它也可以取消它。checked
评论
setTimeout
之所以有效,是因为内部函数在事件流完全完成后执行,该事件流调用了传播的事件对象。:)周围做得很好preventDefault
checkbox
评论
e.preventDefault()
click