4

突然之间,以下代码在针对 KnockoutJS 3.0 时不再有效。我该如何解决这个问题?

JavaScript:

ko.bindingHandlers.limitCharacters = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel)
    {
       element.value = element.value.substr(0, valueAccessor());
       allBindingsAccessor().value(element.value.substr(0, valueAccessor()));
    }
};

HTML:

<textarea data-bind="value: comment, valueUpdate: 'afterkeydown', limitCharacters: 20"></textarea>

见小提琴:http: //jsfiddle.net/ReQrz/1/

4

2 回答 2

6

在 KO 3.0 中,绑定是独立且有序的。您可以在此处阅读有关此内容的更多信息,这应被视为上述链接示例中的“重大更改”:

v2.x 关于绑定之间的依赖关系的行为(在上面关于“独立和有序绑定”的部分中描述)是一个 未记录的内部实现细节,所以希望你不依赖它。但是如果你依赖它,那么显然你会看到行为的变化,因为绑定在 v3 中的设计是独立的。您将需要停止依赖交叉绑定依赖项,顺便说一下,这将使您的代码更加清晰和易于理解。

因此,您的绑定不再起作用,因为它假定当您的comment属性发生更改时,它也会触发您的绑定,limitCharacters尽管您的绑定与该属性limitCharacters无关。comment

解决此问题的一种可能解决方案是,您需要通过使用以下方式访问其值来显式声明对处理程序中value绑定的依赖:updateallBindingsAccessor().value();

ko.bindingHandlers.limitCharacters = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel)
    {
       var val = allBindingsAccessor().value();       
       allBindingsAccessor().value(val.substr(0, valueAccessor()));
    }
};

演示JSFiddle

于 2013-11-21T07:47:28.247 回答
1

nemesv 是完全正确的。

他的修改简短易读。这样做的一个缺点是,当 in 超过限制时,observable 会被调用两次。

如果您不想这样,一个解决方案是创建一个从原始值派生的自定义值绑定器。

(function() {
    var limitValueBindingHandler = {};

    var valueBindingHandler = ko.bindingHandlers.value;
    for(var attr in valueBindingHandler) {
        if (valueBindingHandler.hasOwnProperty(attr)) {
            limitValueBindingHandler[attr] = valueBindingHandler[attr];
        }
    }

    limitValueBindingHandler.init = function(element, valueAccessor, allBindings) {
        var limitCharacters = allBindings.get("limitCharacters");

        element.addEventListener("keydown", function() {
            setTimeout(function() {
                //this is called after the element's value is updated
                //but before value binding event handler
                element.value = element.value.substr(0, limitCharacters);
            }, 0);
        }, false);

        valueBindingHandler.init(element, valueAccessor, allBindings);
    }

    ko.bindingHandlers['limitValue'] = limitValueBindingHandler;
})();

示例:http: //jsfiddle.net/DAFN6/

于 2013-11-21T05:28:16.267 回答