防止敲除 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 的值会在每次击键后发生变化。

我有两个问题:

  1. 既然两个字段都有双向绑定,为什么这只发生在计算的可观察对象(wholeNumber)的情况下,而不是在普通可观察对象的情况下?
  2. 如何在我仍在键入时阻止字段更新。我可以使用 wholeNumber.extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });,但这是次优解决方案。
  1. 关于quantity属性。如果你想在 wholeNumber 改变时更新它,你需要改变你的 wholeNumber 计算定义。因为现在它只改变 cents:

    write: function(value) {
        self.cents(Math.round(value * 100));
    }
    
  2. 关于 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