4

如何更改订阅函数内部的可观察值?例如

JS型号:

function Model(){
    self = this;
    self.Test = ko.observable(2);
    self.Test.subscribe(function (){
      if (/**Some bool expression**/) {
         self.Test(2);
      }
    });
}

HTML:

<input type="radio" value="1" data-bind="checked:Test" />
<input type="radio" value="2" data-bind="checked:Test" />
<input type="radio" value="3" data-bind="checked:Test" />

默认情况下,检查第二个无线电输入。在我点击第一个收音机后,第一个和第二个都被选中。

在此处输入图像描述

更新: 当我同时包含 jQuery 和淘汰赛时会发生这种情况。如果删除 jquery 则一切正常。但这只是测试页面。在实际项目中我需要在某些地方使用 jQuery,在这种情况下我无法删除它。

样品。测试页面来源:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script type="text/javascript" src="knockout-2.1.0.js"></script>
        <script type="text/javascript" src="jquery-1.6.4.js"></script>
        <script type="text/javascript">
            function Model(){
                self = this;
                self.Test = ko.observable(2);
                self.Test.subscribe(function (){
                  if (true) {
                     self.Test(2);
                  }
                });
            }
        </script>
    </head>
<body>
    <input type="radio" value="1" data-bind="checked:Test" />
    <input type="radio" value="2" data-bind="checked:Test" />
    <input type="radio" value="3" data-bind="checked:Test" />
</body>
<script type='text/javascript'>
    ko.applyBindings(new Model());
</script>
</html>
4

2 回答 2

7

更新(2015-02-27):从 Knockout 3.1.0 开始,Knockout 不包含任何click事件的“解决方法”代码,处理问题中的示例应该没有问题。http://jsfiddle.net/9S96U/3/


当包含 jQuery 时,Knockout 使用它来处理事件,包括click用于响应单选按钮的事件。它包含一些“解决方法”代码,以确保单击处理程序看到单选按钮的正确选中状态,但这似乎会干扰您尝试在中间重置选中值的代码。

一种解决方案是使用 setTimeout 更新值。这样它就会在点击处理程序完成后发生。

function Model(){
    var self = this;
    self.Test = ko.observable(2);
    self.Test.subscribe(function (){
        setTimeout(function() {
            self.Test(2);
        });
    });
}

示例:http: //jsfiddle.net/9S96U/1/

此外,您还需要在var之前包含,self = this以免覆盖window.self.

于 2012-10-24T22:41:53.320 回答
0

订阅/发布背后的想法是,您可以让一个观察者将结果发送给多个订阅者,他们自己进行测试。

我还没有真正使用过 knockout.js,但是我已经在委托/异步流/承诺/等方面做了很多工作——主要是针对特殊情况使用轻量级自定义实现。

您的目标是拥有一个控制器,它运行一次测试(您现在拥有的),然后遍历每个控制器,确保i - 1选中正确的一个(),并且所有其他的都未选中......

...或者以更传统的发布者/订阅者方式,让一个发布者(比如fieldset可能是所有无线电控件的父元素)侦听要更改的输入之一,然后通知每个订阅者值的输入,并让他们自己进行测试。

用伪语言:

var subscribers = []; // array of input "Model" callbacks
                      // (ie: tests to determine whether they're off or on)

parentElement.listen("click", function (e) {
        var self = this,
            selectedRadio = e.target,
            val = selectedRadio.value;

        subscribers.forEach(function (notify) { notify(val); });
});

要处理您当前的情况,您可以使用依赖注入:

new Model( value );

或者

new Model( subscription_test_for_element );

您在哪里缓存预期的测试值,或者您在每个实例内部缓存特定于输入的测试/成功/失败逻辑......

...或者您创建一个更大的控制器(不推荐)来处理每个输入的硬编码逻辑。

当然,更具体的帮助可以基于您的模型什么、您如何实例化、为什么要将订阅硬编码到构造中(如果它将成为通用模型)等等。

于 2012-10-24T21:01:24.113 回答