Diese Antwort ist konzeptionell dieselbe wie die von @josh, wird jedoch als allgemeinerer Wrapper dargestellt. Hinweis: Diese Version ist für eine 'beschreibbare' Berechnung.
Ich verwende Typescript, daher habe ich zuerst die ts.d-Definition eingefügt. Ignorieren Sie diesen ersten Teil, wenn er für Sie nicht relevant ist.
interface KnockoutStatic
{
notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
}
Benachrichtigung-beschreibbar-berechnet
Ein Wrapper für eine beschreibbare Datei observable
, der immer dazu führt, dass Abonnenten benachrichtigt werden - auch wenn infolge des write
Aufrufs keine Observables aktualisiert wurden
Ersetzen Sie einfach function<T> (options: KnockoutComputedDefine<T>, context)
mit , function(options, context)
wenn Sie nicht Typoskript verwenden.
ko.notifyingWritableComputed = function<T> (options: KnockoutComputedDefine<T>, context)
{
var _notifyTrigger = ko.observable(0);
var originalRead = options.read;
var originalWrite = options.write;
options.read = () =>
{
_notifyTrigger();
return originalRead();
};
options.write = (v) =>
{
originalWrite(v);
_notifyTrigger(_notifyTrigger() + 1);
};
return ko.computed(options, context);
}
Der Hauptanwendungsfall hierfür ist, wenn Sie etwas aktualisieren, das sonst keine Änderung in einem Observable auslösen würde, das von der read
Funktion "besucht" wird .
Zum Beispiel verwende ich LocalStorage, um einige Werte festzulegen, aber es gibt keine Änderung an beobachtbaren Werten, um eine Neubewertung auszulösen.
hasUserClickedFooButton = ko.notifyingWritableComputed(
{
read: () =>
{
return LocalStorageHelper.getBoolValue('hasUserClickedFooButton');
},
write: (v) =>
{
LocalStorageHelper.setBoolValue('hasUserClickedFooButton', v);
}
});
Beachten Sie, dass alles , was ich brauchte , war Änderung ko.computed
zu ko.notifyingWritableComputed
und dann alles kümmert sich um sich selbst.
Wenn ich hasUserClickedFooButton(true)
anrufe, wird die beobachtbare "Dummy" erhöht, wodurch alle Abonnenten (und ihre Abonnenten) gezwungen werden, den neuen Wert zu erhalten, wenn der Wert in LocalStorage aktualisiert wird.
(Hinweis: Sie denken vielleicht, dass der notify: 'always'
Extender hier eine Option ist - aber das ist etwas anderes).
Es gibt eine zusätzliche Lösung für ein berechnetes Observable, das nur lesbar ist:
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();
Von @mbest Kommentar https://github.com/knockout/knockout/issues/1019 .