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

All*_*ice 17 javascript knockout.js computed-observable

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

我创造了以下小提琴

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);?
Run Code Online (Sandbox Code Playgroud)

HTML:

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

zipcode: 
<span data-bind="text: zipcode"></span>?
Run Code Online (Sandbox Code Playgroud)

我没有使用observable存储,privateZipcode因为那真的只是在cookie中.我希望的是,ko.computed将提供我需要的通知和绑定功能,但大多数的例子我见过ko.computed使用结束了ko.observable封面下方.

不应该将值写入我的计算可观察信号的行为发出与其值绑定的UI元素吗?这些只是更新吗?

解决方法

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

我的解决方法是小提琴,你会注意到唯一改变的是我添加了一个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; 
        }
    }
}();
Run Code Online (Sandbox Code Playgroud)

这是有意义的,并且正如我所期望的那样,因为viewModel.zipcode依赖seperateObservable和更新应该(并且确实)发信号通知用户更新. 我不明白的是,为什么不调用write我的ko.computed信号上的函数更新UI,因为该元素绑定到那个ko.computed

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

All*_*ice 18

叹了口气,我发现有人遇到了同样的问题

如果dependentObservables没有在写入时通知子订阅者,为什么他们甚至懒得在读取时执行此操作?它们被添加到observables列表并订阅,但随后它们永远不会触发更新.那么订阅它们有什么意义呢?

Ryan Niemeyer回答:

我认为对于您的场景,dependentObservables可能不适合这项工作.dependentObservables设置为检测read函数中的依赖项,并在任何这些依赖项发生更改时重新评估/通知.在可写的dependentObservable中,write函数实际上只是一个拦截写入的地方,允许你设置任何必要的observable,这样你的read函数就会返回正确的值(在大多数情况下,write通常与read相反,除非你正在改变价值).

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

这将是:http://jsfiddle.net/rniemeyer/Nn5TH/

所以看起来这个小提琴将是一个解决方案

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);?
Run Code Online (Sandbox Code Playgroud)

这是有道理的,它使用起来更简单.总的来说,由于服务器可以在ajax请求中对其进行编辑等,因此我不确定将cookie视为可观察对象的想法有多大.