防止敲除 textInput 数据绑定在键入时更新字段值
Prevent knockout textInput data-bind from updating the field value while typing
我有这个(非常简单)HTML:
<label>Quantity: <input name="quantity" type="number" data-bind="textInput: quantity"/></label>
<label>Euros: <input name="wholeNumber" type="number" data-bind="textInput: wholeNumber"/></label>
还有这个(也非常简化的)Knockout 模型:
function ViewModel() {
self = this;
cents = ko.observable();
quantity = ko.observable();
wholeNumber = ko.computed({
read: function() {
return (self.cents() / 100).toFixed(2);
},
write: function(value) {
self.cents(Math.round(value * 100));
}
});
}
ko.applyBindings(ViewModel);
请参阅此 fiddle 以获得 运行 宁示例:https://jsfiddle.net/KHFn8/5569/
当我 运行 此代码时,数量的值在键入时不会刷新,但 wholeNumber 的值会在每次击键后发生变化。
我有两个问题:
- 既然两个字段都有双向绑定,为什么这只发生在计算的可观察对象(wholeNumber)的情况下,而不是在普通可观察对象的情况下?
- 如何在我仍在键入时阻止字段更新。我可以使用
wholeNumber.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });
,但这是次优解决方案。
关于quantity
属性。如果你想在 wholeNumber
改变时更新它,你需要改变你的 wholeNumber
计算定义。因为现在它只改变 cents
:
write: function(value) {
self.cents(Math.round(value * 100));
}
关于 wholeNumber.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });
为什么您认为它不是最优的?这是文档中的 "official" 配方 - http://knockoutjs.com/documentation/rateLimit-observable.html
因为它在计算函数中有关于数量的任何过程。您必须在功能中添加数量。例如;
wholeNumber = ko.computed({
read: function() {
return (self.cents() / 100 * self.quantity()).toFixed(2);
},
write: function(value) {
self.cents(Math.round(value * 100));
}
});
作为对第一个问题的回答,即为什么计算绑定会发生但普通可观察对象不会发生:
让我们考虑 wholeNumber
绑定。每次输入字段的值发生变化时,dom-to-computable 绑定都会执行 setter write
,这又会更新 cents
;因为计算的 wholeNumber
依赖于 cents
observable 它订阅了它的所有更改,所以 cents
的更改导致可计算到 dom 绑定执行 read
并更新输入(并将光标移动到输入字段的末尾)。这是一个稍微更新的 jsfiddle,记录了 getter/setter 调用 (https://jsfiddle.net/mdydarfb/)
在普通 observable 的情况下,输入字段的每次更改只会更新绑定 observable 的状态,而不会 "chain reaction"。
作为第二个问题的答案:
如果我正确地理解了这个问题,"turning the tables" 在您的原始代码上就足够了:只需使 cents pureComputed 和 wholeNumber 可观察并将它们绑定在一起 - http://jsfiddle.net/uvmqk4sd/1
我有这个(非常简单)HTML:
<label>Quantity: <input name="quantity" type="number" data-bind="textInput: quantity"/></label>
<label>Euros: <input name="wholeNumber" type="number" data-bind="textInput: wholeNumber"/></label>
还有这个(也非常简化的)Knockout 模型:
function ViewModel() {
self = this;
cents = ko.observable();
quantity = ko.observable();
wholeNumber = ko.computed({
read: function() {
return (self.cents() / 100).toFixed(2);
},
write: function(value) {
self.cents(Math.round(value * 100));
}
});
}
ko.applyBindings(ViewModel);
请参阅此 fiddle 以获得 运行 宁示例:https://jsfiddle.net/KHFn8/5569/
当我 运行 此代码时,数量的值在键入时不会刷新,但 wholeNumber 的值会在每次击键后发生变化。
我有两个问题:
- 既然两个字段都有双向绑定,为什么这只发生在计算的可观察对象(wholeNumber)的情况下,而不是在普通可观察对象的情况下?
- 如何在我仍在键入时阻止字段更新。我可以使用
wholeNumber.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });
,但这是次优解决方案。
关于
quantity
属性。如果你想在wholeNumber
改变时更新它,你需要改变你的wholeNumber
计算定义。因为现在它只改变cents
:write: function(value) { self.cents(Math.round(value * 100)); }
关于
wholeNumber.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });
为什么您认为它不是最优的?这是文档中的 "official" 配方 - http://knockoutjs.com/documentation/rateLimit-observable.html
因为它在计算函数中有关于数量的任何过程。您必须在功能中添加数量。例如;
wholeNumber = ko.computed({
read: function() {
return (self.cents() / 100 * self.quantity()).toFixed(2);
},
write: function(value) {
self.cents(Math.round(value * 100));
}
});
作为对第一个问题的回答,即为什么计算绑定会发生但普通可观察对象不会发生:
让我们考虑 wholeNumber
绑定。每次输入字段的值发生变化时,dom-to-computable 绑定都会执行 setter write
,这又会更新 cents
;因为计算的 wholeNumber
依赖于 cents
observable 它订阅了它的所有更改,所以 cents
的更改导致可计算到 dom 绑定执行 read
并更新输入(并将光标移动到输入字段的末尾)。这是一个稍微更新的 jsfiddle,记录了 getter/setter 调用 (https://jsfiddle.net/mdydarfb/)
在普通 observable 的情况下,输入字段的每次更改只会更新绑定 observable 的状态,而不会 "chain reaction"。
作为第二个问题的答案:
如果我正确地理解了这个问题,"turning the tables" 在您的原始代码上就足够了:只需使 cents pureComputed 和 wholeNumber 可观察并将它们绑定在一起 - http://jsfiddle.net/uvmqk4sd/1