【发布时间】:2018-11-22 02:03:52
【问题描述】:
在某些情况下,ko.computed 不会更新,即使它绑定的 ko.observable 会发生变化。我想知道为什么,我做错了什么以及我应该做什么。
示例
考虑一下这个简单的打数转换器 (JSFiddle here)。
HTML
<label>Dozen:</label><br>
<input type="number" data-bind="value: dozen">
<span class="error" data-bind="text: error"></span><br>
<label>Pieces:</label><br>
<input type="number" data-bind="value: pieces"><br>
JavaScript
function ViewModel() {
var self = this;
self.error = ko.observable('');
self.pieces = ko.observable('');
self.dozen = ko.computed({
read: function() {
var p = parseInt(self.pieces(), 10);
if (!p) return '';
if (p % 12 === 0) return p / 12;
else return '';
},
write: function(value) {
if (/\D/.test(value)) {
self.error('Only whole numbers');
} else {
self.error('');
if (value) self.pieces(value * 12);
}
}
});
}
ko.applyBindings(new ViewModel());
它的作用
它将显示两个输入。一个让您输入几十个(例如 2),另一个将显示有多少个(24)。
您还可以输入多个件(例如 36),转换器将显示有多少个(3)。
如果您在 pieces 框中输入的内容不能被 12 整除,则 dozens 输入将被清除,表示该数字不是偶数。同样,我们不允许用户输入小数。
工作原理
dozens 输入绑定到 KnockoutJS computed observable。它没有自己的价值(也许它在幕后,但这超出了我的知识范围),而是从pieces 属性计算出来的,这是一个常规的observable。要得到几十个,将碎片除以 12,如果结果是整数,则返回,否则返回空字符串。
问题
启动计算器并尝试在dozens 输入中输入1.5。计算器会通知您不允许使用小数。 pieces 字段将保持不变,因为它应该。但是,dozens 输入未清除以反映 pieces 字段的值。
然后在pieces 输入中输入一个新值,例如18。这应该清除 dozens 输入(因为它是一个 computed 仅取决于视图模型的 pieces 属性,并且此值已更改),但它没有。
1.5 的值一直显示在dozens 字段中,即使computed 的read() 函数永远不会返回这样的小数。 computed绑定的observable已经更新,但computed不计算。
只有当您在 pieces 字段中输入可被 12 整除的数字时,dozens 字段才会更新。
我的问题
为什么
dozens输入一直显示1.5,即使read()函数的返回值是空字符串?我可以在write()内部或之后强制一个新的read()或强制更新用户界面吗?我假设
dozens输入即使在更改pieces输入的值后也没有更新的原因是read()函数的结果将是两次空字符串连续,并且 KnockoutJS 在内部缓存了这个值,并看到它没有改变。同样,如何强制更新输入?
【问题讨论】:
标签: knockout.js computed-observable