Почему мои ko вычисляемые наблюдаемые не обновляют связанные элементы пользовательского интерфейса при изменении его значения?
Я пытаюсь обернуть файл cookie в вычисленный наблюдаемый (который позже я перейду в protectedObservable), и у меня возникнут некоторые проблемы с вычисленным наблюдаемым. Я был убежден, что изменения в вычисленном наблюдаемом будут передаваться любым элементам пользовательского интерфейса, которые были привязаны к нему.
Я создал следующую скрипту
JavaScript
var viewModel = {};
// simulating a cookie store, this part isnt as important
var cookie = function () {
// simulating a value stored in cookies
var privateZipcode = "12345";
return {
'write' : function (val) { privateZipcode = val; },
'read': function () { return privateZipcode; }
}
}();
viewModel.zipcode = ko.computed({
read: function () {
return cookie.read();
},
write: function (value) {
cookie.write(value);
},
owner: viewModel
});
ko.applyBindings(viewModel);?
HTML
zipcode:
<input type='text' data-bind="value: zipcode"> <br />
zipcode:
<span data-bind="text: zipcode"></span>?
Я не использую наблюдаемый для хранения privateZipcode
, так как это действительно будет в cookie. Я надеюсь, что ko.computed
предоставит мне необходимые функции уведомлений и привязки, хотя большинство примеров которые я видел с помощью ko.computed
, в конечном итоге используют a ko.observable
под крышками.
Не должен ли акт записи значения для моего вычисленного наблюдаемого сигнала элементам пользовательского интерфейса, привязанным к его значению? Должны ли они просто не обновляться?
Обход
У меня есть простой способ, когда я просто использую ko.observable
рядом с моим хранилищем файлов cookie, и использование этого приведет к появлению необходимых обновлений для моих элементов DOM, но это кажется совершенно ненужным, если только ko.computed
не хватает сигналов/функциональность типа зависимостей, которая ko.observable
имеет.
Моя обходная скрипта, вы заметите, что единственное, что меняется, это то, что я добавил seperateObservable
, который не используется как хранилище, его единственный Цель состоит в том, чтобы сообщить пользовательскому интерфейсу, что базовые данные изменились.
// simulating a cookie store, this part isnt as important
var cookie = function () {
// simulating a value stored in cookies
var privateZipcode = "12345";
// extra observable that isnt really used as a store, just to trigger updates to the UI
var seperateObservable = ko.observable(privateZipcode);
return {
'write' : function (val) {
privateZipcode = val;
seperateObservable(val);
},
'read': function () {
seperateObservable();
return privateZipcode;
}
}
}();
Это имеет смысл и работает так, как я ожидал бы, потому что viewModel.zipcode
зависит от seperateObservable
, и обновления, которые должны (и должны) сигнализировать об обновлении пользовательского интерфейса. Что я не понимаю,, почему не вызов функции write
на моем ko.computed
сигнализирует об обновлении пользовательского интерфейса, поскольку этот элемент привязан к этому ko.computed
?
Я подозревал, что мне, возможно, придется что-то использовать в нокауте, чтобы вручную сообщить, что мой ko.computed
был обновлен, и я в порядке с этим, это имеет смысл. Я просто не смог найти способ сделать это.
Ответы
Ответ 1
Вздох, я нашел кого-то с моя точно такая же проблема
Если dependObservables не уведомляет подписчиков о записи, почему они даже потрудились сделать это при чтении? Они добавляются в список наблюдаемых и подписались на них, но затем они никогда не запускаются при обновлениях. Итак, что точка подписания на них вообще?
Райан Нимейер отвечает:
Я думаю, что для вашего сценария, dependObservables может не быть правильный инструмент для работы. dependentObservables настроены для обнаружения зависимостей в функции чтения и переоценки/уведомления каждый раз, когда этих зависимостей. В зависимости от записи Функция записи - это просто место для перехвата записи и разрешения вы должны установить любые необходимые наблюдаемые данные, чтобы ваша функция чтения вернет правильное значение (запись, как правило, является обратной чтением в большинстве случаев, если вы не преобразуете значение).
В вашем случае я лично использовал бы наблюдаемый для представления а затем ручную подписку на наблюдаемую для обновления оригинальное значение (которое вы не можете контролировать).
Это будет выглядеть так: http://jsfiddle.net/rniemeyer/Nn5TH/
Итак, это выглядит как эта скрипка будет решением
var viewModel = {};
// simulating a cookie store, this part isnt as important
var cookie = function () {
// simulating a value stored in cookies
var privateZipcode = "12345";
return {
'write' : function (val) {
console.log("updated cookie value with: " + val);
privateZipcode = val;
},
'read': function () {
return privateZipcode;
}
}
}();
viewModel.zipcode = ko.observable(cookie.read());
// manually update the cookie when the observable changes
viewModel.zipcode.subscribe(function(newValue) {
cookie.write(newValue);
});
ko.applyBindings(viewModel);
Это имеет смысл и его несколько проще в использовании. В целом я не уверен, насколько велика идея рассматривать cookie как наблюдаемую, поскольку сервер может редактировать ее в ajax-запросе и т.д.
Ответ 2
Попробуйте сделать свой внутренний приватный код видимым. См. Здесь: http://jsfiddle.net/KodeKreachor/fAGes/9/