Knockout bindingHandler用于逗号分隔的数字

lea*_*rrr 8 javascript jquery knockout-2.0 knockout.js

我正在KnockoutJS中构建一个数量很多的应用程序,我希望能够格式化大数字,以便它们以逗号分隔并且很好看(xxx,xxx).

正如您将从下面的小提琴中看到的那样,我确实通过使用简单的RegEx将绑定值包装在格式化函数内部,但问题是这会覆盖输入中的值并将','插入到潜在价值.

大数据在应用程序的下方使用,因此为了防止NaN错误,我必须将数据属性分配给包含没有','的值的输入值,这是存储在sessionStorage中的值.

我觉得我不知不觉地膨胀了我的HTML标记,并相信我想要实现的是一个bindingHandler,但我的绑定处理程序并不完全存在.

小提琴:http://jsfiddle.net/36sD9/2

formatLargeNumber = function (number) {
    if (typeof (number) === 'function') {
        return number().toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }
}

ko.bindingHandlers.largeNumber = {
    init: function(element, valueAccessor) {
        var value = ko.unwrap(valueAccessor());
        var interceptor = ko.computed({
            read: function() {
                return formatLargeNumber(value);
            },
            write: function(newValue) {
                value(reverseFormat(newValue));
            }
        });

        if(element.tagName == 'input' )
            ko.applyBindingsToNode(element, {
                value: interceptor
            });
        else
            ko.applyBindingsToNode(element, {
                text: interceptor
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

nem*_*esv 14

您当前的方法存在多个问题:

  • element.tagName 返回INPUT等,因此在进行比较时需要注意外壳.

  • var value = ko.unwrap(valueAccessor());你正在展开你的observable,所以在你的计算中你正在使用它的值,而不是函数本身.所以你只需要var value = valueAccessor();你需要调用ko.unwrap你的计算read方法.

  • 您不仅需要格式化,而且需要在write方法中"取消格式化" ,但您formatLargeNumber只需要执行格式化方向.

  • 您已申请value和你largeNumber在同一个输入,使两个绑定相互干扰

  • 不要自己编写格式代码只需使用已经这样做的库:http://numeraljs.com/

所以这里是使用numeraljs修正的绑定版本:

ko.bindingHandlers.largeNumber = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        var interceptor = ko.computed({
            read: function() {
                return numeral(ko.unwrap(value)).format('0,0');
            },
            write: function(newValue) {
                value(numeral().unformat(newValue));
                value.valueHasMutated();
            }
        }).extend({notify: 'always'});
        if(element.tagName.toLowerCase() == 'input' )
            ko.applyBindingsToNode(element, {
                value: interceptor
            });
        else
            ko.applyBindingsToNode(element, {
                text: interceptor
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

<input data-bind="largeNumber: testVal">    
Run Code Online (Sandbox Code Playgroud)

演示JSFiddle.