javascript 为什么我的 ko 计算 observable 在其值更改时不更新绑定的 UI 元素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9814320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does my ko computed observable not update bound UI elements when its value changes?
提问by Allen Rice
I'm trying to wrap a cookie in a computed observable (which I'll later turn into a protectedObservable) and I'm having some problems with the computed observable. I was under the opinion that changes to the computed observable would be broadcast to any UI elements that have been bound to it.
我正在尝试将 cookie 包装在一个计算出的 observable(我稍后会变成一个 protectedObservable)中,但我在计算 observable 时遇到了一些问题。我认为对计算的 observable 的更改将广播到任何绑定到它的 UI 元素。
I've created the following fiddle
我创建了以下小提琴
JavaScript:
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:
HTML:
zipcode:
<input type='text' data-bind="value: zipcode"> <br />
zipcode:
<span data-bind="text: zipcode"></span>?
I'm not using an observable to store privateZipcode
since that's really just going to be in a cookie. I'm hoping that the ko.computed
will provide the notifications and binding functionality that I need, though most of the examples I've seenwith ko.computed
end up using a ko.observable
underneath the covers.
我没有使用 observable 来存储,privateZipcode
因为那实际上只是在 cookie 中。我希望的是,ko.computed
将提供通知和绑定功能,我需要,但大多数的例子我见过的与ko.computed
最终使用一个ko.observable
下方的盖子。
Shouldn't the act of writing the value to my computed observable signal the UI elements that are bound to its value? Shouldn't these just update?
将值写入我计算的 observable 的行为不应该向绑定到其值的 UI 元素发出信号吗?这些不应该只是更新吗?
Workaround
解决方法
I've got a simple workaround where I just use a ko.observable
along side of my cookie store and using that will trigger the required updates to my DOM elements but this seems completely unnecessary, unless ko.computed
lacks the signaling / dependency type functionality that ko.observable
has.
我有一个简单的解决方法,我只使用ko.observable
我的 cookie 存储的旁边,使用它会触发对我的 DOM 元素的所需更新,但这似乎完全没有必要,除非ko.computed
缺少具有的信号/依赖类型功能ko.observable
。
My workaround fiddle, you'll notice that the only thing that changes is that I added a seperateObservable
that isn't used as a store, its only purpose is to signal to the UI that the underlying data has changed.
我的解决方法小提琴,你会注意到唯一改变的是我添加了一个seperateObservable
不用作存储的东西,它的唯一目的是向 UI 发出信号,表明底层数据已经改变。
// 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;
}
}
}();
This makes sense and works as I'd expect because viewModel.zipcode
depends on seperateObservable
and updates to that should (and does) signal the UI to update. What I don't understand,is why doesn't a call to the write
function on my ko.computed
signal the UI to update, since that element is bound to that ko.computed
?
这是有道理的,并且按我的预期工作,因为viewModel.zipcode
依赖seperateObservable
和更新应该(并且确实)通知 UI 更新。 我不明白的是,为什么不调用write
我ko.computed
的 UI 信号上的函数来更新,因为该元素绑定到那个ko.computed
?
I suspected that I might have to use something in knockout to manually signal that my ko.computed
has been updated, and I'm fine with that, that makes sense. I just haven't been able to find a way to accomplish that.
我怀疑我可能不得不在淘汰赛中使用某些东西来手动表示我的ko.computed
已更新,我对此很好,这是有道理的。我只是一直无法找到一种方法来实现这一点。
回答by Allen Rice
sigh, I found someone with my exact same problem
叹息,我发现有人遇到了完全相同的问题
If dependentObservables don't notifySubscribers on write, why do they even bother to do it on read? They get added to the observables list and subscribed to, but then they never trigger on updates. So what is the point of subscribing to them at all?
如果dependentObservables 在写入时不通知订阅者,他们为什么还要在读取时通知订阅者呢?它们被添加到 observables 列表并订阅,但它们永远不会在更新时触发。那么订阅它们有什么意义呢?
Ryan Niemeyeranswers:
瑞安·尼迈耶回答:
I think that for your scenario, dependentObservables may not be the right tool for the job. dependentObservables are set up to detect dependencies in the read function and re-evaluate/notify whenever any of those dependencies change. In a writeable dependentObservable, the write function is really just a place to intercept the write and allow you to set any observables necessary, such that your read function would return the proper value (write is typically the reverse of read in most cases, unless you are transforming the value).
For your case, I would personally use an observable to represent the value and then a manual subscription to that observable to update the original value (the one that you may not have control over).
It would be like: http://jsfiddle.net/rniemeyer/Nn5TH/
我认为对于您的情况,dependentObservables 可能不是适合该工作的工具。dependentObservables 被设置为检测读取函数中的依赖关系,并在这些依赖关系中的任何一个发生变化时重新评估/通知。在可写的dependentObservable中,写函数实际上只是一个拦截写的地方,并允许您设置任何必要的可观察对象,这样您的读函数将返回正确的值(在大多数情况下,写通常与读相反,除非您正在改变价值)。
对于您的情况,我个人会使用 observable 来表示值,然后手动订阅该 observable 以更新原始值(您可能无法控制的值)。
So it looks like this fiddlewould be a solution
所以看起来这个小提琴将是一个解决方案
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);?
That makes sense and its somewhat simpler to use. Overall I'm not sure how great of an idea it is to treat a cookie as an observable since the server could edit it in an ajax request, etc.
这是有道理的,而且使用起来更简单一些。总的来说,我不确定将 cookie 视为可观察对象是一个多么棒的想法,因为服务器可以在 ajax 请求等中编辑它。
回答by KodeKreachor
Try making your internal privatezipcode an observable. See here: http://jsfiddle.net/KodeKreachor/fAGes/9/
尝试使您的内部 privatezipcode 成为可观察的。见这里:http: //jsfiddle.net/KodeKreachor/fAGes/9/