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ビンジングも発生すると想定されているため、バインディングはもう機能しません。limitCharacterscomment

これを修正するための可能な解決策の 1 つは、次の値を使用してハンドラーの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は完全に正しいです。

彼の修正は短く、読みやすいです。その欠点の 1 つは、オブザーバブルが制限を超えると 2 回呼び出されることです。

それを望まない場合の解決策は、オリジナルから派生したカスタム値バインダーを作成することです。

(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 に答える