計算されたプロパティを考える
_vm.checkedValueCount = ko.computed(function(){
var observables = getCurrentValues(); //an array of ko.observable[]
return _.filter(observables, function(v) { return v() }).length;
});
_
getCurrentValues()が、コード内の他の場所で変更された(およびobservableArrayよりも複雑な構造に由来する)オブザーバブルの異なるセットを返すことができると仮定します。
常に更新するにはcheckedValueCount
が必要です
問題は、_ko.computed
_が最後に返された値をメモし、依存関係が更新されたときにのみ更新されるように見えることです。これは最初のケースを処理しますが、後者は処理しません。
私が探しているのは、checkedValueCountを強制的に再実行する方法です。私が使用できるもの:
_changeCurrentValues();
vm.checkeValueCount.recalculate();
_
私が持っていることを考えると、最も簡単に言えば
_a = ko.computed(function() { return Math.random() })
_
a()
を2回呼び出して異なる値を返すにはどうすればよいですか。
私の最初の答えがあなたの主張を逃し、あなたの問題を解決できないことに気づきました。
問題は、再評価を強制する観察可能なものがある場合にのみ、計算されたものが再評価されることです。計算されたものを強制的に再評価するネイティブな方法はありません。
ただし、ダミーの観測可能な値を作成し、サブスクライバーに値が変更されたことを伝えることで、いくつかのハッカーでこれを回避できます。
(function() {
var vm = function() {
var $this = this;
$this.dummy = ko.observable();
$this.curDate = ko.computed(function() {
$this.dummy();
return new Date();
});
$this.recalcCurDate = function() {
$this.dummy.notifySubscribers();
};
};
ko.applyBindings(new vm());
}());
これはフィドルです このアプローチを示しています
メソッド があり、あなたに応じてすべてのオブザーバブルの再計算を強制します:
getCurrentValues.valueHasMutated()
この答えは概念的には@joshが与えたものと同じですが、より一般的なラッパーとして提示されます。注:このバージョンは、「書き込み可能」計算用です。
TypeScriptを使用しているため、最初にts.d定義を含めました。関係ない場合は、この最初の部分を無視してください。
_interface KnockoutStatic
{
notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
}
_
observable
のラッパー-write
呼び出しの結果としてオブザーバブルが更新されなかった場合でもTypeScriptを使用しない場合は、function<T> (options: KnockoutComputedDefine<T>, context)
をfunction(options, context)
に置き換えてください。
_ko.notifyingWritableComputed = function<T> (options: KnockoutComputedDefine<T>, context)
{
var _notifyTrigger = ko.observable(0);
var originalRead = options.read;
var originalWrite = options.write;
// intercept 'read' function provided in options
options.read = () =>
{
// read the dummy observable, which if updated will
// force subscribers to receive the new value
_notifyTrigger();
return originalRead();
};
// intercept 'write' function
options.write = (v) =>
{
// run logic provided by user
originalWrite(v);
// force reevaluation of the notifyingWritableComputed
// after we have called the original write logic
_notifyTrigger(_notifyTrigger() + 1);
};
// just create computed as normal with all the standard parameters
return ko.computed(options, context);
}
_
これの主な使用例は、read
関数によって「訪問された」オブザーバブルの変更をトリガーしないような何かを更新する場合です。
たとえば、LocalStorageを使用していくつかの値を設定していますが、再評価をトリガーするためのオブザーバブルに変更はありません。
_hasUserClickedFooButton = ko.notifyingWritableComputed(
{
read: () =>
{
return LocalStorageHelper.getBoolValue('hasUserClickedFooButton');
},
write: (v) =>
{
LocalStorageHelper.setBoolValue('hasUserClickedFooButton', v);
}
});
_
変更する必要があるのは_ko.computed
_から_ko.notifyingWritableComputed
_であり、すべてが自分で処理することに注意してください。
hasUserClickedFooButton(true)
を呼び出すと、 'ダミー'オブザーバブルがインクリメントされ、LocalStorageの値が更新されたときにすべてのサブスクライバー(およびそのサブスクライバー)に新しい値を強制的に取得させます。
(注:ここでは_notify: 'always'
_エクステンダーがオプションであると思われるかもしれません-しかし、それは別のものです)。
Readbleのみである計算されたオブザーバブルには、追加のソリューションがあります。
_ko.forcibleComputed = function(readFunc, context, options) {
var trigger = ko.observable().extend({notify:'always'}),
target = ko.computed(function() {
trigger();
return readFunc.call(context);
}, null, options);
target.evaluateImmediate = function() {
trigger.valueHasMutated();
};
return target;
};
myValue.evaluateImmediate();
_
@mbestコメントから https://github.com/knockout/knockout/issues/1019 。
getCurrentValues()がコードの他の場所で変更された異なるオブザーバブルのセットを返すことができると仮定します
GetCurrentValues()は関数だと思います。計算できる場合、checkedValueCountは魔法のように動作し始めます。
GetCurrentValuesを関数ではなく計算式にすることはできますか?