81

与えられた計算されたプロパティ

vm.checkedValueCount = ko.computed(function(){
  var observables = getCurrentValues();  //an array of ko.observable[]
  return _.filter(observables, function(v) { return v() }).length;
});

getCurrentValues() が、コード内の他の場所で変更されたさまざまなオブザーバブルのセットを返すことができるとします (また、observableArray よりも複雑な構造に由来します)。

checkedValueCountいつでも更新したい

  • その依存関係の 1 つが変更されます
  • getCurrentValues() は、異なるオブザーバブルのセットを返します。

問題はko.computed、最後に返された値をメモ化し、依存関係が更新されたときにのみ更新されるように見えることです。これは最初のケースを処理しますが、後者は処理しません。

私が探しているのは、checkedValueCount を強制的に再実行する方法です。私が次のように使用できるもの:

changeCurrentValues();
vm.checkeValueCount.recalculate();

最も簡単に言えば、私が持っていることを考えると

a = ko.computed(function() { return Math.random() })

強制的に 2 回呼び出しa()て異なる値を返すにはどうすればよいですか。

4

5 に答える 5

118

私の最初の回答があなたの要点を逃しており、あなたの問題を解決できないことに気付きました。

問題は、再評価を強制するオブザーバブルがある場合にのみ、計算済みが再評価されることです。計算結果を強制的に再評価するネイティブな方法はありません。

ただし、ダミーの観察可能な値を作成し、それが変更されたことをサブスクライバーに伝えることで、いくつかのハッカーでこれを回避できます。

(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());

}());​

これは、このアプローチを示すフィドルです

于 2012-12-07T19:41:25.900 に答える
8

あなたのものに応じて、すべてのオブザーバブルの再計算を強制する方法があります:

getCurrentValues.valueHasMutated()
于 2014-11-10T18:42:26.243 に答える
4

この回答は、概念的には @josh が提供したものと同じですが、より一般的なラッパーとして提示されています。注: このバージョンは「書き込み可能な」計算用です。

私は Typescript を使用しているので、最初に ts.d 定義を含めました。したがって、あなたに関係ない場合は、この最初の部分を無視してください。

interface KnockoutStatic
{
    notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
}

Notifying-writeable-computed

呼び出しの結果としてオブザーバブルが更新されなかった場合でも、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 .

于 2015-04-30T05:57:43.390 に答える
1

getCurrentValues() が、コード内の他の場所で変更されたさまざまなオブザーバブル セットを返すことができるとします。

getCurrentValues() は関数だと思います。計算されたものにすることができれば、checkedValueCount は魔法のように機能し始めます。

getCurrentValues を関数の代わりに計算することはできますか?

于 2012-12-07T19:26:52.027 に答える