我正在创建基于ajax的应用程序。现在我正在使用客户端javascript。我创建了根据应用程序逻辑正常工作的控制器,但我在更新包含复选框的视图时遇到问题。 以下是我正在做的简短示例:
<script type='text/javascript'>
var model = { 'chk1': true, 'chk2': false, 'chk3': false };
var Controller = {
'processCheck': function(chk, value) {
model[chk] = value;
if (chk == 'chk2')
model.chk2 = true;
if (chk == 'chk3' && value)
model.chk1 = false;
if (chk == 'chk1' && model.chk3)
model.chk1 = false;
Controller.updateView();
},
'updateView': function() {
$('#chk1').attr('checked', model.chk1);
$('#chk2').attr('checked', model.chk2);
$('#chk3').attr('checked', model.chk3);
}
}
</script>
<input id='chk1' type="checkbox" onclick="Controller.processCheck('chk1', $('#chk1').attr('checked')); return false;" />
<input id='chk2' type="checkbox" onclick="Controller.processCheck('chk2', $('#chk2').attr('checked')); return false;" />
<input id='chk3' type="checkbox" onclick="Controller.processCheck('chk3', $('#chk3').attr('checked')); return false;" />
因此逻辑非常简单。 单击复选框时出现问题。它们更新不正确。 但是如果我用适当的参数调用控制器方法,然后检查模型,那么一切似乎都是正确的。 所以问题在于复选框中的click事件。 我对输入字段和下拉列表没有任何问题。
答案 0 :(得分:3)
click
(和checkbox
)上的radio
事件很奇怪且令人困惑。
原则上,它发生在鼠标交互点,在点击导致复选框改变其状态之前。因此,return false
或event.preventDefault
应该可以取消进行状态更改的默认操作。在这种情况下,永远不要触摸复选框的状态。
但是,这并不是大多数浏览器实际发生的情况。在回溯到古代Netscape的一些历史怪癖中,checked
事件处理程序中复选框的click
属性实际上是新值。 click事件本身已经导致复选框改变状态。然后,如果您阻止默认操作(return false
),浏览器会显示“哎呀,抱歉,这个更改从未发生过”,会主动将复选框翻转回其旧值。
这意味着如果您故意在点击处理程序中的脚本中故意设置复选框的状态,那么该值将会丢失,由浏览器奇怪的尝试在原始点击的更改时关闭时钟而被覆盖。
因此,反直觉地说,未能return false
并且阻止默认操作实际上会导致浏览器干扰更少!另一个解决方案是:
setTimeout(Controller.updateView, 0);
而不是直接在点击处理程序中调用updateView
。这使浏览器有机会在之前翻转其状态,从模型中覆盖它。您甚至可以将除return false
之外的整个事件处理程序置于0超时。
理论上,正确的解决方案是使用onchange
而不是onclick
。此事件明确发生在状态更改之后,因此您根本不必担心这种奇怪现象及其浏览器兼容性。 onchange
的问题在于IE不会像它应该的那样快速地触发它;等待焦点在触发前移出复选框,就像在文本输入上一样。所以至少在那个浏览器上,为了保持一致性,你需要点击0超时。
答案 1 :(得分:0)
Diodeus走在正确的轨道上,return false;
导致了您的问题。由于您的updateView
函数每次都会设置所有检查,因此您无需担心它会被暂时检查,因为它的发生速度会比用户无论如何都要快。使用return false;
,将忽略用户点击的复选框checked
函数中updateView
状态的设置。
简而言之,从所有return false;
函数中删除onclick
,您的代码应该按照您想要的方式运行。