web-dev-qa-db-ja.com

値が変更されたときに、koが計算したobservableがバインドされたUI要素を更新しないのはなぜですか?

計算されたオブザーバブル(後でprotectedObservableに変換します)でCookieをラップしようとしていますが、計算されたオブザーバブルに問題があります。計算されたオブザーバブルへの変更は、それにバインドされているすべての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);?

[〜#〜] html [〜#〜]

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

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

privateZipcodeを格納するためにオブザーバブルを使用していません。これは、実際にはCookieに格納されるためです。 ko.computedが必要な通知とバインド機能を提供することを期待していますが、ほとんどの 私が見た例ko.computedは最終的にko.observableカバーの下。

計算された監視可能な値に値を書き込むという行為は、その値にバインドされているUI要素に信号を送るべきではありませんか?これらはただ更新するべきではありませんか?

Workaround

Cookieストアの横でko.observableを使用するだけで、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; 
        }
    }
}();

viewModel.zipcodeseperateObservableに依存し、それを更新するとUIに更新を通知する必要があるため、これは理にかなっており、期待どおりに機能します。 私が理解していないこと、は、私のko.computedシグナルでwrite関数を呼び出さない理由です。その要素はそのko.computedにバインドされているため、更新するUI?

ko.computedが更新されたことを手動で通知するには、ノックアウトで何かを使用する必要があるのではないかと思いました。それで問題ありません。それは理にかなっています。私はそれを達成する方法を見つけることができませんでした。

17
Allen Rice

ため息、私は 私のまったく同じ問題

DependentObservablesが書き込み時にSubscribersに通知しない場合、なぜ読み取り時にわざわざ通知するのでしょうか。それらはオブザーバブルリストに追加されてサブスクライブされますが、更新時にトリガーされることはありません。では、それらをサブスクライブする意味は何ですか?

ライアンニーマイヤー 答え:

あなたのシナリオでは、dependentObservablesはその仕事に適したツールではないかもしれないと思います。 dependentObservablesは、読み取り関数の依存関係を検出し、それらの依存関係のいずれかが変更されるたびに再評価/通知するように設定されています。書き込み可能なdependentObservableでは、書き込み関数は実際には書き込みをインターセプトする場所であり、読み取り関数が適切な値を返すように、必要なオブザーバブルを設定できます(書き込みは通常、読み取りの逆です。値を変換しています)。

あなたの場合、私は個人的にオブザーバブルを使用して値を表し、次にそのオブザーバブルへの手動サブスクリプションを使用して元の値(あなたが制御できない可能性があるもの)を更新します。

次のようになります: 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);​

それは理にかなっており、使用するのはやや簡単です。全体として、サーバーがajaxリクエストなどでCookieを編集できるため、Cookieを監視可能なものとして扱うことがどれほど素晴らしいかはわかりません。

18
Allen Rice

内部のprivatezipcodeを監視可能にしてみてください。ここを参照してください: http://jsfiddle.net/KodeKreachor/fAGes/9/

0
KodeKreachor