0

我正在尝试使用 KnockoutJS 实现类型安全的 ViewModel 之类的东西。在我开始通过 HTML 输入标签更新 observables 之前,它工作得很好。

我已经实现了type扩展器,它返回计算的 observable:

return ko.computed({
    read: target,
    write: fixer
})

fixer类似的东西在哪里:

function (newValue) {
    var current = target(),
        valueToWrite = (newValue == null ? null : fixNumber(newValue, 0));

    if (valueToWrite !== current) target(valueToWrite);
    else if (newValue !== current) target.notifySubscribers(valueToWrite);
}

并且fixNumber

function fixNumber(value, precision) {
    if (value == null || value === '') return null;

    var newValue = (value || '').toString().replace(/^[^\,\.\d\-]*([\.\,\-]?\d*)([\,\.]?\d*).*$/, '$1$2').replace(/\,/, '.'),
        valueToWrite = Number(newValue);

    return !!(valueToWrite % 1) ? round(valueToWrite, precision) : valueToWrite;
}

它看起来不是那么简单,但我必须考虑可能使用逗号作为小数分隔符。

通常,一旦用户按下键以立即反映此更改,我需要立即更新我的 observables:

<input type="text" data-bind="value: nonThrottled, valueUpdate: 'afterkeyup'"></input>

这里有很多问题,例如,我不能在那里输入小于 1 的十进制值(0.1、0.2 等)。

当我尝试限制 observable 时,它​​主要是有效的。但有时用户输入和类型修复程序会不同步,因此看起来某些输入偶尔会丢失。

完整的例子是http://jsfiddle.net/mailgpa/JHztW/。我真的很感激任何提示,因为我花了几天时间试图解决这些问题。

2013 年 11 月 4 日更新

我解决了提供自定义value绑定的问题,所以现在节流的 observables 不会偶尔吃掉我的输入。

我添加了额外的 valueThrottle 选项绑定来限制元素值的更新:

var valueThrottle = allBindingsAccessor()["valueThrottle"];
var valueThrottleTimeoutInstance = null;

/* ... */

if (valueThrottle) {
    clearTimeout(valueThrottleTimeoutInstance);
    valueThrottleTimeoutInstance = setTimeout(function () {
      ko.selectExtensions.writeValue( element, ko.utils.unwrapObservable(valueAccessor()) );
    }, valueThrottle);
  } else applyValueAction();

此外,我注意到在我的情况下无法输入像 0.2 这样的值来自原始value绑定中的该语句:

if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
    valueHasChanged = true;

我把它改写为

if ((newValue === 0) && (elementValue != 0))
    valueHasChanged = true;

它至少在 Chrome 上工作,但我没有正确测试它,甚至不确定它是否正确。

将添加示例,由于某种原因 jsFiddle 不接受我的自定义绑定。

任何评论都非常感谢。

4

0 回答 0