57

現在、dom要素のjQueryデータを使用して状態を保存しています。

ko.bindingHandlers.customValue = {

    init: function init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var state = { isEditing: false };        
        $(element).focus(function focus() {
            state.isEditing = true;
        }).blur(function blur() {
            state.isEditing = false;            
        }).data("customBinding", state);

    },

    update: function update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // ignore if updating
        if (!$(element).data("customBinding").isEditing) {
            // handle update if they are not updating                                
        }
    }

};​

domを必要としないバインディングごとの状態を保存するためのより良い場所はありますか?bindingContextを使用して、バインディングの各インスタンスの状態を保存できますか?

4

5 に答える 5

48

これは可能ですが、バインディングが最初にトリガーされたときにbindingContextデータを渡すためだけです。次に発火すると、それはもう存在しません。initupdateupdate

このタイプの状態を保存する場所には、実際には 2 つの選択肢があります。

1-あなたが述べたように、要素について。jQuery$.dataまたは KO インクルード API を使用して、これを行うko.utils.domData.get(element, key)こともできますko.utils.domData.set(element, key, value)

2- 必要に応じて、このタイプの情報をビュー モデルに入れます。示すフラグisEditingは、ビュー モデルでは必ずしも場違いではありません。私は個人的に、このタイプの「メタデータ」を次のようなオブザーバブルからサブオブザーバブルとして配置するのが好きです。

var name = ko.observable("Bob");
name.isEditing = ko.observable(false);

nameとに対してバインドできますname.isEditing

これにはいくつかの利点があります。

  • 新しいトップレベルのプロパティを導入していないため、ビューモデルをかなりきれいに保ちます
  • サブオブザーバブルをその親オブザーバブルに結び付けたままにします(nameIsEditingなどは必要ありません)
  • ko.toJSONsub-observableのようなもので JSON に変換するisEditingと、その親がアンラップされたときに単にドロップされます。したがって、不要な値をサーバーに送り返すことはありません。
  • この場合、ビュー モデル内の他の計算に使用できる、または UI 内の複数の要素にバインドできるという利点もあります。
于 2012-04-17T01:17:18.687 に答える
9

要素にデータを添付することは問題ありません。たとえば、Knockout はこのメソッドを制御フロー バインディング (if、with など) に内部的に使用します。

別の方法は、init関数のみを使用し、計算されたオブザーバブルを使用して更新を処理することです。このメソッドは、繰り返しバインディングで使用します。重要な部分は次のとおりです。

ko.bindingHandlers['repeat'] = {
    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ...
        // set up persistent data
        var lastRepeatCount = 0;
        ...
        ko.computed(function() {
            var repeatCount = ko.utils.unwrapObservable(valueAccessor());
            ...
            // Remove nodes from end if array is shorter
            for (; lastRepeatCount > repeatCount; lastRepeatCount--) {
                ...
            }
            ...
            // Add nodes to end if array is longer (also initially populates nodes)
            for (; lastRepeatCount < repeatCount; lastRepeatCount++) {
                ...
            }
        }, null, {'disposeWhenNodeIsRemoved': placeholder});
        ...
    }
};
于 2012-05-15T01:56:40.453 に答える
2

この質問は古いと思いますが、アプローチを探してここでつまずいたので、より現代的な ko メソッドに参加したいと思いました。

プロパティを bindingContext.$data に直接追加するだけです。衝突の可能性を避けるために、煩わしい変数名「___IsEditing」を選択しましたが、お分かりいただけると思います...

ko.bindingHandlers.customValue = {

init: function init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    bindingContext.$data.___IsEditing = false;        
    $(element).focus(function focus() {
        bindingContext.$data.___IsEditing = true;
    }).blur(function blur() {
        bindingContext.$data.___IsEditing = false;            
    }).data("customBinding", state);

},

update: function update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    // ignore if updating
    if (bindingContext.$data.___IsEditing) {
        // handle update if they are not updating                                
    }
}

}; </p>

于 2016-12-29T15:38:06.167 に答える
-2

関数内で共通データを定義することにより、関数を使用して init と update の共通スコープを作成します。

于 2016-12-29T23:52:14.690 に答える