为什么对复选框单击事件的preventDefault对checked属性返回true?

Dav*_*ain 6 javascript checkbox

我只是很好奇,需要对以下情况作一些解释.

假设我有一个类型为checkbox的输入元素,并附加了一个eventlistener,侦听click事件.我阻止复选框的默认行为并记录复选框的选中状态,该状态将始终返回true.

复选框的可视化表示告诉我它没有被选中.所以我假设检查状态将返回false.我相信这肯定是愚蠢的,我绝对会误解这里的事情.有趣的是,我也在记录事件本身.在目标属性内部,checked属性设置为false,就像我预期的那样.

根据我的理解,防止默认将取消事件而不停止传播,那么到底发生了什么?

如果有人可以在这一点上启发我会很棒.这是一个例子.

var checkbox = document.getElementsByTagName('input')[0],
    output = document.getElementById('output');

checkbox.addEventListener('click', function(evt) {
  evt.preventDefault();
  output.innerHTML = "Checkbox checked attribute is " + this.checked;
  console.log(this.checked, evt.target.checked);
  console.log(evt);
}, false);
Run Code Online (Sandbox Code Playgroud)
<input type="checkbox" id="my-checkbox" />
<label for="my-checkbox">Checkbox with preventDefault().</label>
<div id="output"></div>
Run Code Online (Sandbox Code Playgroud)

sod*_*tea 9

实际上,处理程序中的checked值的结果click依赖实现的.

正如我在多个浏览器中测试的那样,在这种情况下,Chrome/Firefox/Safari/Opera将始终返回true,但如果您继续单击该复选框元素,则IE/Edge的行为会有点奇怪.

我在规范中找到了这一段,这可能是对这种不一致的解释:

注意:在处理具有值为"radio"或"checkbox"的type属性的input元素上的click事件期间,某些实现可能会在文档中调度事件之前更改此属性的值.如果取消事件的默认操作,则可以将属性的值更改回其原始值.这意味着在处理单击事件期间此属性的值取决于实现.

但是当我删除该preventDefault语句时,IE/Edge中的结果与其他浏览器一致,这让我感到困惑.

所以我不认为这是IE/Edge的预期行为...因此我在Microsoft Connect上提交了一个错误.


毕竟,如果我们假设Chrome的行为符合标准,那么以下可能是一个合适的解释:

根据HTML规范,input[type=checkbox]元素的检查性在取消的激活过程中恢复,该过程在事件处理程序之后根据激活部分进行.因此,在执行事件处理程序期间,元素的检查性尚未恢复.

(规范没有明确说明已取消的激活步骤必须在所有事件处理程序之后;但是很容易推断,否则无法确定事件的取消状态)


小智 5

根据 w3schools 的说法“如果事件可取消,preventDefault() 方法会取消该事件,这意味着属于该事件的默认操作将不会发生。” 单击事件是可取消的(您可以像这样检查它 console.log("cancelable?"+ evt.cancelable);。所以据我所知,复选框对象的单击事件的默认行为是读取当前状态一个复选框并在 true 和 false 之间交替,因此将其状态更改为选中和未选中。简而言之,默认行为是切换;因此, preventDefault() 取消该行为。

关于复选框选中 = true; unchecked = false。如果您尝试逐步调试并遵循 eventListener,您将看到,一旦进入其中,即使在踩到evt.preventDefault()之后,未选中的框也会变为“选中”,因此当您调用 console.log(this.checked) 时, evt.target.checked); 那时对于编译器,您的框被“选中”,只有当 eventListener 完成执行时复选框才会返回到“未选中”状态。由此我可以得出结论,如果在事件侦听器中的所有调用都被执行之后,在复选框中preventDefault() 实际上被激活(执行)

图像代表上面段落中描述的一些步骤