自定义绑定在KnockoutJS 3.0中不再工作

Custom binding no longer working in KnockoutJS 3.0

本文关键字:不再 工作 绑定 KnockoutJS 自定义      更新时间:2023-09-26

突然之间,以下代码在针对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/

在KO 3.0中,绑定是独立的和有序的。你可以在这里阅读更多关于这一点的信息,这应该被认为是一个"突破性的变化",来自上面链接的例子:

v2.x关于绑定之间依赖关系的行为(在上面关于"独立和有序绑定"的部分),是未记录的内部实现细节所以希望您没有依赖它。但如果你依赖它,那么显然你会查看行为的变化,因为绑定在v3中是独立的设计您需要停止依赖交叉绑定依赖项,顺便说一句,这将使您的代码更干净、更容易懂

所以绑定不再工作,因为它假设当comment属性更改时,它也会触发limitCharacters绑定,尽管limitCharacters绑定与comment属性无关。

解决此问题的一个可能的解决方案是,您需要在update处理程序中显式声明对value绑定的依赖关系,方法是使用allBindingsAccessor().value();:访问其值

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

演示JSFiddle。

nemesv是完全正确的。

他的修改内容简短易读。然而,它的一个缺点是,当in超过极限时,可观察到的被调用两次。

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

(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/