Ця відповідь концептуально така ж, як і @josh, але представлена як більш загальна обгортка. Примітка: ця версія призначена для обчислювального запису.
Я використовую Typescript, тому спочатку включив визначення ts.d. Тож ігноруйте цю першу частину, якщо вона не стосується вас.
interface KnockoutStatic
{
notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
}
Повідомлення-запис-обчислення
Обгортка для запису, observable
яка завжди призводить до сповіщення передплатників - навіть якщо в результатіwrite
дзвінка
Просто замініть function<T> (options: KnockoutComputedDefine<T>, context)
на, function(options, context)
якщо ви не використовуєте Typescript.
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);
}
Основним випадком використання для цього є те, коли ви оновлюєте щось, що інакше не викликало б змін у спостережуваному, яке "відвідує" 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'
розширювач тут є варіантом - але це щось інше).
Існує додаткове рішення для обчислюваного спостережуваного, яке можна лише прочитати:
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 .