强制计算属性函数运行

给定一个计算的属性

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

假设getCurrentValues()可以返回代码中其他地方修改的不同的可观察集合(来自比observableArray更复杂的结构)。

我需要checkedValueCount来更新

  • 它的一个依赖关系发生了变化
  • getCurrentValues()返回一组不同的观察值。

问题是, ko.computed似乎memoize最后返回的值,只有更新时,依赖项更新。 这处理第一个案件,但不是后者。

我正在寻找的方法是强制checkedValueCount重新运行。 一些我可以使用的东西:

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

最简单的,因为我有

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

我怎么能强制调用a()两次返回不同的值。

我意识到我的第一个答案错过了你的观点,并不会解决你的问题。

问题是如果有一些可观察的结果迫使它重新评估,计算结果将只会重新评估。 没有原生的方法来强制计算重新评估。

然而,你可以通过创build一个虚拟的可观察值,然后告诉它的订阅者它已经改变来解决这个问题。

 (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(options, context)replacefunction<T> (options: KnockoutComputedDefine<T>, 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函数“访问”的observable的变化时。

例如,我使用LocalStorage来设置一些值,但没有任何可观察到的变化来触发重新评估。

 hasUserClickedFooButton = ko.notifyingWritableComputed( { read: () => { return LocalStorageHelper.getBoolValue('hasUserClickedFooButton'); }, write: (v) => { LocalStorageHelper.setBoolValue('hasUserClickedFooButton', v); } }); 

请注意,所有我需要改变ko.computedko.notifyingWritableComputed ,然后一切照顾自己。

当我调用hasUserClickedFooButton(true)那么'dummy'可观察值将增加,迫使任何订阅者(及其订阅者)在LocalStorage中的值更新时获取新值。

(注意:你可能会认为notify: 'always'扩展是这里的一个选项 – 但这是不同的)。


有一个额外的解决scheme,只有可读的计算观察值:

 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是一个计算而不是一个函数?

因为没有直接的方法来强制更新计算,我已经创build了一个名为toForceComputedUpdate的可观察值,我在计算函数内调用它,所以计算将监听它的更新,然后强制更新我像这样调用它toForceComputedUpdate(Math 。随机)