Cette réponse est conceptuellement la même que celle donnée par @josh, mais elle est présentée sous une forme plus générique. Note : cette version est pour un calcul 'inscriptible'.
J'utilise Typescript et j'ai donc inclus la définition ts.d en premier. Ignorez donc cette première partie si elle ne vous concerne pas.
interface KnockoutStatic
{
notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
}
Notification de l'écriture calculée
Une enveloppe pour un fichier observable
que toujours entraîne la notification des abonnés, même si aucun observable n'a été mis à jour à la suite de l'opération write
appel
Il suffit de remplacer function<T> (options: KnockoutComputedDefine<T>, context)
con function(options, context)
si vous n'utilisez pas Typescript.
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);
}
Le principal cas d'utilisation est la mise à jour d'un élément qui ne déclencherait pas de changement dans un observable "visité" par la fonction read
fonction.
Par exemple, j'utilise LocalStorage pour définir certaines valeurs, mais aucun observable n'est modifié pour déclencher une réévaluation.
hasUserClickedFooButton = ko.notifyingWritableComputed(
{
read: () =>
{
return LocalStorageHelper.getBoolValue('hasUserClickedFooButton');
},
write: (v) =>
{
LocalStorageHelper.setBoolValue('hasUserClickedFooButton', v);
}
});
Notez que tout ce que j'ai eu besoin de changer était ko.computed
a ko.notifyingWritableComputed
et tout s'arrangera tout seul.
Lorsque j'appelle hasUserClickedFooButton(true)
l'observable "factice" est alors incrémenté, ce qui oblige tous les abonnés (et leurs abonnés) à obtenir la nouvelle valeur lorsque la valeur de LocalStorage est mise à jour.
(Note : vous pouvez penser que le notify: 'always'
est une option ici - mais c'est quelque chose de différent).
Il existe une solution supplémentaire pour une observable calculée qui n'est que lisible :
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();
Extrait du commentaire de @mbest https://github.com/knockout/knockout/issues/1019 .