这个答案在概念上与@josh 给出的答案相同,但呈现为更通用的包装器。注意:此版本适用于“可写”计算。
我使用的是 Typescript,所以我首先包含了 ts.d 定义。因此,如果与您无关,请忽略第一部分。
interface KnockoutStatic
{
notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
}
通知可写计算
一个可写的observable 的包装器,总是导致订阅者收到通知 - 即使没有任何 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 函数“访问”的 observable 更改的内容时。
例如,我正在使用 LocalStorage 设置一些值,但没有任何可观察到的变化来触发重新评估。
hasUserClickedFooButton = ko.notifyingWritableComputed(
{
read: () =>
{
return LocalStorageHelper.getBoolValue('hasUserClickedFooButton');
},
write: (v) =>
{
LocalStorageHelper.setBoolValue('hasUserClickedFooButton', v);
}
});
请注意,我只需要将ko.computed 更改为ko.notifyingWritableComputed,然后一切都会自行处理。
当我调用 hasUserClickedFooButton(true) 时,'dummy' observable 会递增,强制任何订阅者(及其订阅者)在 LocalStorage 中的值更新时获取新值。
(注意:您可能认为notify: 'always' 扩展器是这里的一个选项 - 但这是不同的)。
对于只可读的计算 observable 有一个额外的解决方案:
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。