【问题标题】:Knockout bindingHandler for comma separated numbers逗号分隔数字的敲除 bindingHandler
【发布时间】:2014-04-20 09:09:47
【问题描述】:

我正在使用 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
            });
    }
}

有什么想法吗?

【问题讨论】:

    标签: javascript jquery knockout.js knockout-2.0


    【解决方案1】:

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

    • element.tagName 返回 INPUT 等,因此在进行比较时需要注意大小写。

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

    • 您不仅需要格式化,还需要在write 方法中“取消格式化”,但您的formatLargeNumber 只做格式化方向。

    • 您在同一输入上应用了valuelargeNumber,这使得这两个绑定相互干扰

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

    所以这里是使用 numericjs 绑定的更正版本:

    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
                });
        }
    }
    

    并像这样使用它:

    <input data-bind="largeNumber: testVal">    
    

    演示JSFiddle.

    【讨论】:

    • 非常感谢!小提琴工作正常,但是当我将它复制到本地副本中时,在向输入字段写入新值后,我得到“未捕获的错误:除非您指定“写入”选项,否则无法将值写入 ko.computed。如果您希望读取当前值,不要传递任何参数。” - 有什么想法会导致这种情况吗?
    • 你在哪一行得到错误?错误消息暗示您将 largeNumber 与 ko.computed 一起使用,因此 data-bind="largeNumber: yourComputed" 但由于这是双向绑定,您只能将其与可写计算或常规 observables 一起使用。
    • 啊,我在计算函数上使用它是的。这是因为输入的值实际上是基于从 中选择的值依赖/生成的
    • 嗨@nemesv,你有空的时候可以看看我在这里面临的问题(stackoverflow.com/q/23803394/847872)吗?我试图修改您的解决方案。谢谢
    • @Aamir 嗨,你只需要写:value.valueHasMutated(); 在拦截器的write 方法中:jsfiddle.net/8YgNg 所以我在这里修复了我的答案,如果这对你来说很好,然后您可以删除您的其他问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2019-02-12
    • 2013-05-09
    • 1970-01-01
    相关资源
    最近更新 更多