私は複雑なビューモデルを持っています。これは、大量の監視可能なプロパティ、計算された監視可能なプロパティ、書き込み可能な計算された監視可能なプロパティと関数を備えた数百行のJavaScriptコードです。したがって、これを管理することはかなりの課題です。
私が対処しなければならなかった厄介な問題は、計算されたオブザーバブルが定義するとすぐに計算されることです。したがって、オブザーバブルを定義する時点でビューモデルでまだ定義されていない変数を使用すると、変数が定義されていないことを示すエラーが発生します。それは...ファイルのすぐ後でです。
不自然な例を次に示します。
function ViewModel1(args) {
var self = this;
self.firstName = ko.observable(args.firstName);
self.lastName = ko.observable(args.lastName);
self.fullName = ko.computed(function () {
return self.firstName() + ' ' + self.lastName();
});
}
function ViewModel2(args) {
var self = this;
self.fullName = ko.computed(function () {
// uh oh, where's firstName?
return self.firstName() + ' ' + self.lastName();
});
self.firstName = ko.observable(args.firstName);
self.lastName = ko.observable(args.lastName);
}
使用ViewModel1
しても問題なく動作します。その時点fullName
で定義され、firstName
期待lastName
どおりに機能するように定義されます。使用ViewModel2
は機能しません。計算された関数にエラーがあり、firstName
定義されていません。
これまで私が行ってきたのは、すべての従属変数が定義された後に、計算されたすべてのオブザーバブルが確実に定義されるようにすることでした。これに伴う問題は、そうすることで、関連する変数を互いに近づけて定義したいときに、一見ランダムな場所で物事が定義されることです。
私が思いついた1つの優れた解決策は、「初期化」オブザーバブルセットを定義し、true
すべての計算されたオブザーバブルがまだ初期化されているかどうかをテストし、そうでない場合は値を計算して返すことです。そうすれば、現在未定義の変数にアクセスする試みは行われません。
function ViewModel3(args) {
var self = this;
var initializing = ko.observable(true);
self.fullName = ko.computed(function () {
if (!initializing()) {
return self.firstName() + ' ' + self.lastName();
}
});
self.firstName = ko.observable(args.firstName);
self.lastName = ko.observable(args.lastName);
initializing(false);
}
しかし、私の場合、これはあまり実用的ではありません。私は計算されたオブザーバブルをたくさん持っているので、それらすべてでこれを行うと非常に肥大化するでしょう、私がこれらをたくさん持っていることを覚えておいてください。それを絞ることは違いを生まないようです。
計算されたオブザーバブルの値を計算する前に待機するようにノックアウトに指示する方法はありますか?または、これに対処するためにコードを構造化するためのより良い方法はありますか?
初期化ロジックを管理するためにいくつかのヘルパー関数を作成することもできますが、それでも、計算された監視可能な定義をすべて変更する必要があります。ノックアウトにこのようなオプションがあることに気付いていないので、この初期化ロジックを追加するためにモンキーパッチノックアウトを使用できると思います。以前に計算されたオブザーバブルのソースを調べましたが、他の場所にすでに設定があるかどうかはわかりません。