使用 javascript 控制器中的复选框

发布于 2024-10-01 18:50:29 字数 1342 浏览 6 评论 0原文

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

所以逻辑非常简单。 当我们点击复选框时就会出现问题。它们更新不正确。 但是,如果我使用适当的参数调用控制器方法,然后检查模型,一切似乎都是正确的。 所以问题出在复选框中的单击事件。 我的输入字段和下拉菜单没有任何问题。

I'm creating ajax based application. Now I'm working with client side javascript. I created controller which works correctly according to application logic, but i have problems with updating views which contains checkboxes.
Here is short example of what I'm doing:

<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;" />

So logic is very simplified.
Problems occurs when we click on checkboxes. They are updated incorrectly.
But if I call controller methods with appropriate parameters, and then check model, all seems to be correct.
So problem is with click event in checkboxes.
I did not have any problems with input fields and dropdowns.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你在我安 2024-10-08 18:50:29

checkbox(和radio)上的click事件很奇怪且令人困惑。

原则上,它发生在鼠标交互时,在单击导致复选框更改其状态之前。因此,应该可以返回 falseevent.preventDefault 来取消进行状态更改的默认操作。在这种情况下,决不应该触及复选框的状态。

然而,这并不是大多数浏览器中实际发生的情况。由于一些可以追溯到古代 Netscape 的历史怪癖,在 click 事件处理程序期间复选框的 checked 属性实际上是新值。单击事件本身已经导致复选框更改状态。然后,如果您阻止默认操作(返回 false),浏览器会说“哎呀,抱歉,该更改根本没有发生”,并且主动将复选框翻转回其旧值

这意味着,如果您碰巧在单击处理程序内的脚本中故意设置了复选框的状态,则该值将丢失,并被浏览器在原始单击更改上调回时钟的奇怪尝试所覆盖。

因此,与直觉相反,未能返回 false 并阻止默认操作实际上会导致浏览器干扰更少!另一个修复是:

setTimeout(Controller.updateView, 0);

而不是直接在点击处理程序中调用 updateView。这使浏览器有机会在您从模型覆盖它之前翻转其状态。您甚至可以将除 return false 之外的整个事件处理程序设置为 0 超时。

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

The click event on checkbox (and radio) is strange and confusing.

In principle, it is happening at the point of mouse interaction, before the click has caused the checkbox to change its state. Consequently, it should be possible to return false or event.preventDefault to cancel the default action of making that state change. In this case the the checkbox's state should never be touched.

However, this is not what actually happens in most browser. Out of some historical quirk stretching back to ancient Netscape, the checked property of the checkbox during the click event handler is in fact the new value. The click event itself already causes the checkbox to change state. Then if you prevent the default action (return false), the browser says “oops, sorry, that change never happened after all” and actively flips the checkbox back to its old value.

This means that if you happened to deliberately set the state of the checkbox from script inside the click handler, that value will be lost, overwritten by the browser's weird attempt to turn back the clock on the original click's change.

So, counter-intuitively, failing to return false and prevent the default action actually causes the browser to interfere less! Another fix is:

setTimeout(Controller.updateView, 0);

instead of calling updateView directly in the click handler. This gives the browser the opportunity to flip back its state before you overwrite it from the model. You can even put the whole of the event handler other than the return false on a 0-timeout.

The proper solution would theoretically be to use onchange instead of onclick. This event unequivocally occurs after the state change, so you don't have to worry about this weirdness and its browser compatibility at all. The problem with onchange is that IE doesn't fire it as fast as it should; it waits for focus to move out of the checkbox before firing, like on a text input. So at least on that browser, for consistency, you'd need the 0-timeout-on-click instead.

胡大本事 2024-10-08 18:50:29

Diodeus 走在正确的轨道上,return false; 导致了您的问题。由于您的 updateView 函数每次都会设置所有检查,因此您无需担心它会被暂时检查,因为这一切都会比用户看到的速度更快。使用 return false; 时,用户单击的复选框的 updateView 函数中的 checked 状态设置将被忽略。

简而言之,从所有 onclick 函数中删除 return false;,您的代码就应该按照您想要的方式工作。

Diodeus was on the right track, the return false; is causing your problems. Since your updateView function sets all the checks everytime, you don't need to worry about it being momentarily checked, since it will all happen faster than the user can see anyhow. With the return false;, the setting of the checked status in the updateView function for the checkbox that the user clicked will be ignored.

In short, remove the return false; from all the onclick functions, and your code should work the way you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文