为啥我的 ko 计算 observable 在其值更改时不会更新绑定的 UI 元素?
Posted
技术标签:
【中文标题】为啥我的 ko 计算 observable 在其值更改时不会更新绑定的 UI 元素?【英文标题】:Why does my ko computed observable not update bound UI elements when its value changes?为什么我的 ko 计算 observable 在其值更改时不会更新绑定的 UI 元素? 【发布时间】:2012-04-06 13:04:00 【问题描述】:我正在尝试将一个 cookie 包装在一个计算的 observable 中(我稍后会变成一个 protectedObservable),但我在计算 observable 时遇到了一些问题。我认为对计算出的 observable 的更改将被广播到任何绑定到它的 UI 元素。
我创建了the following fiddle
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>?
我没有使用 observable 来存储 privateZipcode
,因为它实际上只是在 cookie 中。我希望ko.computed
将提供我需要的通知和绑定功能,尽管大多数examples I've seen 和ko.computed
最终在封面下使用ko.observable
。
将值写入我计算的 observable 的行为不应该向绑定到其值的 UI 元素发出信号吗?这些不应该更新吗?
解决方法
我有一个简单的解决方法,我只需在我的 cookie 存储旁边使用 ko.observable
并使用它会触发对我的 DOM 元素的所需更新,但这似乎完全没有必要,除非 ko.computed
缺少信号 / ko.observable
具有的依赖类型功能。
My workaround fiddle,你会注意到唯一改变的是我添加了一个不用作存储的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;
();
这是有道理的,并且可以按我的预期工作,因为viewModel.zipcode
依赖于seperateObservable
,并且对其进行更新应该(并且确实)通知 UI 进行更新。 我不明白, 是为什么我的ko.computed
上的write
函数调用没有通知UI 更新,因为该元素绑定到ko.computed
?
我怀疑我可能不得不在淘汰赛中使用某些东西来手动表示我的ko.computed
已更新,我对此很好,这是有道理的。我只是无法找到一种方法来实现这一点。
【问题讨论】:
【参考方案1】:sigh,我找到了my exact same problem的人
如果dependentObservables 在写入时不通知订阅者,他们为什么要这样做 甚至懒得看书?它们被添加到 observables 列表中 并订阅了,但是他们永远不会触发更新。那么什么是 订阅它们的意义何在?
Ryan Niemeyer 答案:
我认为对于您的场景,dependentObservables 可能不是 适合工作的工具。设置dependentObservables 来检测 读取函数中的依赖关系,并在任何时候重新评估/通知 这些依赖项发生了变化。在可写的dependentObservable 中, write 函数实际上只是一个拦截写入并允许的地方 您可以设置任何必要的可观察值,以便您的读取功能 将返回正确的值(写通常与读相反 在大多数情况下,除非您正在转换值)。
对于您的情况,我个人会使用 observable 来表示 值,然后手动订阅该 observable 以更新 原始值(您可能无法控制的值)。
就像:http://jsfiddle.net/rniemeyer/Nn5TH/
所以看起来this fiddle 将是一个解决方案
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/
【讨论】:
它实际上是通过$.cookie.get()
和$.cookie.set()
写入/读取该值,在我的示例中通过cookie
模拟。除了我在ko.computed
observable 中尝试做的事情之外,我没有能力让它成为可观察的。这个想法是ko.computed
将封装写入/读取cookie,这就是为什么我不喜欢使用subscribe
。
是的,但是如果您的 cookie 对象没有任何内在的东西可以被淘汰赛依赖跟踪系统跟踪,那么您可能不走运。如果您只是将内部 privateZipcode 设为可观察,那么您应该能够看到值更新。
所以 cookie 对象本身不是 observable,它只包含一个 observable,以便在写入时可以对其进行跟踪。
基本上你的建议与尼迈耶相同,我会为此 +1。他通过基本上说“将其存储在可观察对象中并订阅它”,更进一步(这就是我所要理解的)。通过这样做,它完全消除了拥有ko.computed
的需要。这是这两种方法的唯一区别。以上是关于为啥我的 ko 计算 observable 在其值更改时不会更新绑定的 UI 元素?的主要内容,如果未能解决你的问题,请参考以下文章
KnockoutJS 查找 ko.observable() 长度
将 ko observables 组合成一个 ko observable 数组