使用javascript控制器中的复选框

使用javascript控制器中的复选框,javascript,jquery,model-view-controller,checkbox,click,Javascript,Jquery,Model View Controller,Checkbox,Click,我正在创建基于ajax的应用程序。现在我正在使用客户端javascript。我创建了根据应用程序逻辑正常工作的控制器,但在更新包含复选框的视图时遇到了问题。 以下是我正在做的简短示例: <script type='text/javascript'> var model = { 'chk1': true, 'chk2': false, 'chk3': false }; var Controller = { 'processCheck': function

我正在创建基于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;" />

var模型={'chk1':true,'chk2':false,'chk3':false};
变量控制器={
“processCheck”:函数(chk,值){
模型[chk]=值;
如果(chk=='chk2')
model.chk2=真;
如果(chk=='chk3'&&value)
model.chk1=假;
如果(chk=='chk1'&&model.chk3)
model.chk1=假;
Controller.updateView();
},
'updateView':函数(){
$('chk1').attr('checked',model.chk1);
$('#chk2').attr('checked',model.chk2');
$('chk3').attr('checked',model.chk3');
}
}
所以逻辑非常简单。 单击复选框时会出现问题。它们更新不正确。 但若我用适当的参数调用控制器方法,然后检查模型,那个么一切似乎都是正确的。 所以问题在于复选框中的单击事件。 我对输入字段和下拉列表没有任何问题。

在正确的轨道上,
返回false导致了您的问题。由于您的
updateView
函数每次都会设置所有检查,因此您不必担心它会被临时检查,因为它的速度比用户所能看到的要快。使用
返回false
,用户单击的复选框的
更新查看
功能中的
选中状态设置将被忽略


简而言之,删除
返回falseonclick
功能中选择code>,您的代码应该按照您想要的方式工作。

复选框上单击
事件(和
收音机
)既奇怪又混乱

原则上,它发生在鼠标交互点,在单击导致复选框更改其状态之前。因此,应该可以
返回false
event.preventDefault
以取消更改该状态的默认操作。在这种情况下,永远不要触摸复选框的状态

然而,这并不是大多数浏览器中实际发生的情况。出于追溯到古代Netscape的一些历史怪癖,在
单击期间,复选框的
checked
属性实际上是新值。单击事件本身已导致复选框更改状态。然后,如果您阻止默认操作(
返回false
),浏览器会说“哦,对不起,那次更改根本就没有发生过”,并主动将复选框翻转回原来的值

这意味着,如果您碰巧在单击处理程序中故意从脚本设置复选框的状态,则该值将丢失,并被浏览器奇怪地试图将原始单击的更改时间倒转所覆盖

因此,与直觉相反,未能
返回false
并阻止默认操作实际上会减少浏览器的干扰!另一个解决方案是:

setTimeout(Controller.updateView, 0);
而不是直接在单击处理程序中调用
updateView
。这使浏览器有机会在您从模型中覆盖之前反转其状态。您甚至可以将整个事件处理程序(而不是
return false
设置为0超时)


理论上,正确的解决方案是使用
onchange
而不是
onclick
。此事件明确地发生在状态更改之后,因此您根本不必担心这种奇怪现象及其浏览器兼容性。onchange的问题在于IE没有以应有的速度启动它;它等待焦点移出复选框,然后再触发,就像在文本输入上一样。因此,至少在该浏览器上,为了保持一致性,您需要0-timeout-on-click来代替。

我知道如何选中和取消选中复选框。还有一个问题。实际上我使用的是$('#id').attr('checked',true);和$('id').attr('checked',false);为什么在你的onclick中出现“return false”?单击没有被任何东西调用,因此没有返回值;我不希望通过单击来更新复选框。我希望他们只调用控制器方法,然后控制器更新其中一些方法。请确认第一次单击复选框2时所期望的行为吗?+1关于复选框单击事件和其他控件之间存在问题的差异的有趣解释。我同意@jball。这很有趣,谢谢!setTimeout(Controller.updateView,0);为我工作!就像许多晦暗、令人不快的网络历史包袱一样,这最终被记录和标准化(“点击前激活步骤”、“取消激活步骤”)。谢谢你的回答,但这对我不起作用。这段代码只是一个简单的示例,在这里我们可以删除“returnfalse”,但在我的项目中,我使用的是嵌套元素的复杂结构。有一个要求,我的代码不应该将任何事件冒泡到它的父控件。我可以通过使用事件对象来防止默认操作,但这会使代码的理解和调试变得更加复杂。为了避免现在的问题,对于未来的开发人员来说,我们总是阻止来自控件的任何事件,只调用Controllers方法,并且如果需要,控制器会更新相应的视图necessary@SerhiyPrysyazhnyy-很有意义,@bobince提供的使用
setTimeout
的解决方案肯定会很好地适应这种结构。