1つのページに複数のビューモデルがある場合、それらを同期し続けることができるようにするにはどうすればよいですか?たとえば、1つのアイテムが追加されたり、1つのビューモデルでボタンがクリックされ、他のビューモデルがその変更に敏感であるようにしたい場合、Knockoutはこれをネイティブに管理できますか、メッセージングまたはpub/subアーキテクチャを使用する方が適切です。
モデル間のオブザーバブルを管理する必要がないようにしたい。
1つのページに複数のビューモデルがある場合、それらを同期し続けることができるようにするにはどうすればよいですか?たとえば、1つのアイテムが追加されたり、1つのビューモデルでボタンがクリックされ、他のビューモデルがその変更に敏感であるようにしたい場合、Knockoutはこれをネイティブに管理できますか、メッセージングまたはpub/subアーキテクチャを使用する方が適切です。
モデル間のオブザーバブルを管理する必要がないようにしたい。
Knockout 2.0には、基本的なpub/subを実行できる機能が含まれています。これは、2つのビューモデルがメディエーターを介して通信するサンプルです。
var postbox = new ko.subscribable();
var ViewModelOne = function() {
this.items = ko.observableArray(["one", "two", "three"]);
this.selectedItem = ko.observable();
this.selectedItem.subscribe(function(newValue) {
postbox.notifySubscribers(newValue, "selected");
});
};
var ViewModelTwo = function() {
this.content = ko.observable();
postbox.subscribe(function(newValue) {
this.content(newValue + " content");
}, this, "selected");
};
ko.applyBindings(new ViewModelOne(), document.getElementById("choices"));
ko.applyBindings(new ViewModelTwo(), document.getElementById("content"));
最初のビューモデルは特定のトピックについてポストボックスを介して通知し、2番目のビューモデルはそのトピックをサブスクライブします。それらは互いに直接依存していません。
確かに、ポストボックスはグローバルである必要はなく、ビューモデルコンストラクター関数に渡すことも、自己実行関数内に作成することもできます。
サンプル: http: //jsfiddle.net/rniemeyer/z7KgM/
また、は(関数を含む)postbox
だけである可能性もあります。ko.observable
ko.subscribable
あなたは矛盾した目標に向かって進んでいるようです。Knockoutでそれを行う方法は、オブザーバブルを作成することですが、それでもあなたはそれを望んでいないようです。
オブザーバブルを備えたFooおよびBarオブジェクトがある場合、バーまたはその逆と相互作用するFoo上のオブザーバブルは必要ないかもしれませんが、FooおよびBarを監視して仲介するウィジェットを用意してみませんか?
私は最近の私のプロジェクトのためにこの問題を解決するために小さな拡張機能を作成しました。方法論は少し似ていますが、公開されたオブザーバブルに直接サブスクリプションを追加し、公開されたオブザーバブルの宣言の前に宣言された場合、サブスクライバーをキューに入れます。
モデルを同期する方法は、RPNiemeyerのポストボックスライブラリを使用することです。
しかし、observableArrayに関して何か面白いものを見つけました。そしてそれが私が新しい答えを作成した理由です。ニーマイヤーからの答えを完成させるためだけに。
postboxとobservableArrayを使用する場合、observableArrayに要素を追加または削除すると、「subscribeTo」イベントと「publishOn」イベントが発生します。配列内の要素を更新しても、何も発生しません。これはポストボックスライブラリとは何の関係もありませんが、ノックアウトの制限があると思います。
監視可能な配列の要素を更新するときにイベントを取得しようとしている場合は、ポストボックスライブラリの「publish」メソッドと「subscribe」メソッドを使用することをお勧めします。
次のFIDDLEをご覧ください
コードリファレンス:
function FundEntity (fund)
{
var self = this;
self.id = fund.id;
self.fundName = fund.fundName;
self.description = fund.description;
self.isFavorite = ko.observable(fund.isFavorite);
}
function GridViewModel(model) {
var self = this;
self.fundList = ko.observableArray();
model.funds.forEach(function(fund) {
self.fundList.push(new FundEntity(fund));
});
self.favorite = function (id, index) {
var newValue = {
id: id,
index: index,
isFavorite: self.fundList()[index].isFavorite()
};
ko.postbox.publish("itemChanged", newValue);
return true;
};
self.isEditable = ko.observable().subscribeTo("myEditableTopic");
}
function FundDetailViewModel(model) {
var self = this;
self.fundList = ko.observableArray();
model.funds.forEach(function(fund) {
self.fundList.push(new FundEntity(fund));
});
ko.postbox.subscribe("itemChanged", function (newValue) {
self.fundList()[newValue.index].isFavorite(newValue.isFavorite);
});
self.editable = ko.observable(false).publishOn("myEditableTopic");
}