为什么我的ko计算的observable在其值发生变化时不会更新绑定的UI元素?

时间:2012-03-21 23:26:52

标签: javascript knockout.js computed-observable

我正在尝试将一个cookie包装在一个计算的observable中(后来我将其变成一个protectedObservable),并且我对计算的observable有一些问题。我认为对计算出的observable的更改将广播到已绑定到它的任何UI元素。

我创建了the following fiddle

的JavaScript

var viewModel = {};

// simulating a cookie store, this part isnt as important
var cookie = function () {  

    // simulating a value stored in cookies
    var privateZipcode = "12345";

    return {
        'write' : function (val) { privateZipcode = val; }, 
        'read': function () { return privateZipcode; }
    }
}();

viewModel.zipcode = ko.computed({
        read: function () {
            return cookie.read();
        },
        write: function (value) {
            cookie.write(value);
        },
        owner: viewModel
    });

ko.applyBindings(viewModel);?

HTML

zipcode:
<input type='text' data-bind="value: zipcode"> <br />

zipcode: 
<span data-bind="text: zipcode"></span>?

我没有使用observable存储privateZipcode,因为那真的只是在cookie中。我希望ko.computed能够提供我需要的通知和绑定功能,尽管大多数examples I've seen ko.computed最终会使用ko.observable

将值写入计算的observable的行为不应该表示绑定到其值的UI元素吗?这些不应该更新吗?

解决方法

我有一个简单的解决方法,我只是在我的cookie商店旁边使用ko.observable并使用它将触发我的DOM元素所需的更新,但这似乎完全没必要,除非ko.computed缺少ko.observable具有的信令/依赖类型功能。

My workaround fiddle,您会注意到唯一改变的是我添加了一个未用作商店的seperateObservable,它的唯一目的是向UI发出信号。数据已经改变。

// simulating a cookie store, this part isnt as important
var cookie = function () {  

    // simulating a value stored in cookies
    var privateZipcode = "12345";

    // extra observable that isnt really used as a store, just to trigger updates to the UI
    var seperateObservable = ko.observable(privateZipcode);

    return {
        'write' : function (val) { 
            privateZipcode = val; 
            seperateObservable(val);
        }, 
        'read': function () { 
            seperateObservable();
            return privateZipcode; 
        }
    }
}();

这是有意义的,并且正如我所期望的那样,因为viewModel.zipcode取决于seperateObservable,并且对它的更新应该(并且确实)指示要更新的UI。 我不明白,是为什么我的write上的ko.computed函数调用不会通知UI更新,因为该元素绑定到{ {1}}?

我怀疑我可能不得不在淘汰赛中使用某些东西来手动发出我的ko.computed已经更新的信号,而我对此很好,这是有道理的。我只是无法找到实现这一目标的方法。

2 个答案:

答案 0 :(得分:18)

叹了口气,我找到了my exact same problem

的人
  

如果dependentObservables在写入时没有通知子订阅者,为什么会这样做   读书时甚至懒得去做?它们被添加到observables列表中   并订阅,但他们永远不会触发更新。那是什么   订阅它们的重点是什么?

Ryan Niemeyer回答:

  

我认为对于您的场景,dependentObservables可能不是   适合工作的正确工具。 dependentObservables设置为检测   read函数中的依赖项,并在任何时候重新评估/通知   这些依赖关系的变化。在可写的dependentObservable中,   写入函数实际上只是一个拦截写入和允许的地方   你要设置任何必要的可观察量,以便你的阅读功能   将返回正确的值(写入通常与读取相反   在大多数情况下,除非你正在改变价值)。

     

对于你的情况,我个人会使用一个observable代表   值,然后手动订阅该observable来更新   原始值(您可能无法控制的值)。

     

就像:http://jsfiddle.net/rniemeyer/Nn5TH/

所以看起来this fiddle将是一个解决方案

var viewModel = {};

// simulating a cookie store, this part isnt as important
var cookie = function () {  

    // simulating a value stored in cookies
    var privateZipcode = "12345";

    return {
        'write' : function (val) { 
            console.log("updated cookie value with: " + val);
            privateZipcode = val; 
        }, 
        'read': function () { 
            return privateZipcode; 
        }
    }
}();

viewModel.zipcode = ko.observable(cookie.read());

// manually update the cookie when the observable changes
viewModel.zipcode.subscribe(function(newValue) {
   cookie.write(newValue);   
});

ko.applyBindings(viewModel);​

这很有意义,而且使用起来有点简单。总的来说,由于服务器可以在ajax请求等中编辑它,我不确定将cookie视为可观察的想法有多棒。

答案 1 :(得分:0)

尝试将内部privatezipcode设为可观察对象。见这里:http://jsfiddle.net/KodeKreachor/fAGes/9/