56

私はまだKnockoutの適切な使用法を学んでおりko.observable、ビューモデルを設定するときに入力するのをすぐにやめ、代わりにオブジェクトリテラルを定義し、次のようなものを使用してマッピングプラグインに渡すことに気付きました。

var viewModel = ko.mapping.fromJS(data);

または、少なくとも、すべてのデータをviewModelの属性に詰め込むという方針に沿った何かが

var viewModel = { 
    ... events etc ... , 
    "data": ko.mapping.fromJS(data)
}

正直なところ、私がこれを行ってきた主な理由は、入力しなければならないことを回避するためko.observableですko.observableArrayvar x = ko.observable()これが良いアプローチであるかどうか、そして特定の宣言をまとめて削除することの欠点があるかどうかを理解しようとしています。また、私はこれをすべてロード時に行っており、ajax呼び出しなどに応答していません。これは、私が知る限り、マッピングプラグインが設計された目的です。

ノックアウトを使用した作業では、オブザーバブルを1つずつ手動で宣言しますか、それとも私が使用するmapping.fromJSメソッドを使用しましたか?このように頻繁にマッピングプラグインを使用することの特定の欠点はありますか?

編集:

具体例

この記事では、スティーブは次のようにしてviewModelを設定します

var initialData = [ { ... } , { ... } ]; // json from the serializer
var viewModel = {
    gifts : ko.observableArray(initialData)
};

通常、私はko.mapping.fromJSこの状況にも使用します。具体的には、配列内のオブジェクトが監視可能になっていることを確認するためです。彼が何をしたかを見ると、私のアプローチはやり過ぎのようで、少し不必要なオーバーヘッドが追加されます。

4

4 に答える 4

59

Knockoutをもう少し長く使用した後、マッピングプラグインに、マッピングプロセスをよりきめ細かく制御できるいくつかの追加オプションがあることに気付きました。

生成されるプロパティのタイプと量を制御する

これを実現する方法はいくつかあります。いくつか説明しますが、すべてが観察可能ではないため、最終的にはマッピングプラグインの結果がより明るくなります。

基本的に、変更されるとは思わないものはすべて通常のプロパティとして残し、観察したい特定のアイテムからのみ観察可能なものを作成します。

特定のプロパティをmapping省略します

ignoreまたはのようなものを指定することにより、マッピングプラグインに最終結果からプロパティを完全に省略させることができますinclude。これらは両方とも、まったく逆の方法で同じことを達成します。

注:サンプルは、knockout.jsマッピングプラグインのドキュメントからのものです。コメントは私が追加しました

マッピングプラグイン引数:include

次のスニペットは、引数 を介して渡されたプロパティ以外のすべてのプロパティをソースオブジェクトから省略します。include

// specify the specific properties to include as observables in the end result 
var mapping = {
    // only include these two properties
    'include': ["propertyToInclude", "alsoIncludeThis"]
}

// viewModel will now only contain the two properties listed above, 
//    and they will be observable
var viewModel = ko.mapping.fromJS(data, mapping);

マッピングプラグイン引数:ignore

ソースオブジェクトから特定のプロパティのみを省略したい場合は、ignore以下に示すように引数を使用します。指定されたプロパティを除く、ソースオブジェクトのすべてのプロパティからオブザーバブルを作成します。

// specify the specific properties to omit from the result, 
//    all others will be made observable
var mapping = {
    // only ignore these two properties
    'ignore': ["propertyToIgnore", "alsoIgnoreThis"]
}

// viewModel will now omit the two properties listed above, 
//    everything else will be included and they will be an observable
var viewModel = ko.mapping.fromJS(data, mapping);

監視可能にするプロパティとしないプロパティを制御します

プロパティを含める必要があるが、(何らかの理由で)それらを監視可能にする必要がないと思われる場合は、マッピングプラグインに役立つ機能があります。

マッピングプラグイン引数:copy

マッピングプラグインでプレーンプロパティを単純にコピーし、それらを監視可能にしないようにする場合は、以下に示すように、この引数を使用します。

// tell the mapping plugin to handle all other properties normally, 
//    but to simply copy this property instead of making it observable
var mapping = {
    'copy': ["propertyToCopy"]
}
var viewModel = ko.mapping.fromJS(data, mapping);

マッピングプロセスを完全に制御できます

オブジェクトにクロージャやサブスクリプションを配置する機能など、マッピングプロセスで作成されるものを100%制御したい場合は、「作成」オプションを使用します。

計算されたプロパティを含む単純な結果

これは、ajax呼び出しからのデータをresultsプロパティを持つオブジェクトにマッピングしていた例です。観察可能なものは必要ありませんでした。オブジェクトの他の単純なプロパティで構成される、単純に生成されたプロパティが必要でした。おそらく最も説得力のある例ではありませんが、機能を示しています。

var searchMappingConfig = {
    // specific configuration for mapping the results property
    "results": {
                    // specific function to use to create the items in the results array
        "create": function (options) {
            // return a new function so we can have the proper scope/value for "this", below
            return new function () {

                // instead of mapping like we normally would: ko.mapping.fromJS(options.data, {}, this);
                // map via extend, this will just copy the properties from the returned json element to "this"
                // we'll do this for a more light weight vm since every last property will just be a plain old property instead of observable
                $.extend(this, options.data);

                // all this to add a vehicle title to each item
                this.vehicleTitle = this.Year + "<br />" + this.Make + " " + this.Model;
                }, this);
            };
        }
    }
}

サブスクリプションとクロージャとマッピング

もう1つの状況は、結果にクロージャとサブスクリプションが必要な場合です。この例は長すぎて全体を含めることはできませんが、車両のメーカー/モデル階層の場合です。モデルが有効になっていない場合は、特定のメーカー(親)のすべてのモデル(子)を無効にし、サブスクリプションを使用してこれを実行する必要がありました。

// here we are specifying the way that items in the make array are created, 
//    since makes has a child array (Models), we will specify the way that 
//    items are created for that as well
var makesModelsMappingConfig = {
   // function that has the configuration for creating makes
   "create": function (options) {
      // return a new function so we can have the proper 
      //    scope/value for "this", below
      return new function () {

         // Note: we have a parent / child relationship here, makes have models. In the 
         //    UI we are selecting makes and then using that to allow the user to select 
         //    models. Because of this, there is going to be some special logic in here 
         //    so that all the child models under a given make, will automatically 
         //    unselect if the user unselects the parent make.

         // make the selected property a private variable so it can be closure'd over
         var makeIsSelected = ko.protectedComputed(false);

         // expose our property so we can bind in the UI
         this.isSelected = makeIsSelected;

         // ... misc other properties and events ...

         // now that we've described/configured how to create the makes, 
         //    describe/configure how to create the models under the makes
         ko.mapping.fromJS(options.data, {
            // specific configuration for the "Models" property                  
            "Models": {
               // function that has the configuration for creating items 
               //    under the Models property
               "create": function (model) {

                  // we'll create the isSelected as a local variable so 
                  //    that we can flip it in the subscription below, 
                  //    otherwise we wouldnt have access to flip it
                  var isSelected = ko.protectedComputed(false);

                  // subscribe to the parents "IsSelected" property so 
                  //    the models can select/unselect themselves
                  parentIsSelected.current.subscribe(function (value) {
                     // set the protected computed to the same 
                     //    value as its parent, note that this 
                     //    is just protected, not the actual value
                     isSelected(value);
                  });


                  // this object literal is what makes up each item 
                  //    in the Models observable array 
                  return {
                     // here we're returning our local variable so 
                     //    we can easily modify it in our subscription
                     "isSelected": isSelected,

                     // ... misc properties to expose 
                     //     under the item in the Model array ...

                  };
               }
            }
         }, this);
      };
   }
};

全体として、私が見つけたのは、プラグインに渡すオブジェクトの100%が必要になることはめったになく、監視可能にするためにオブジェクトの100%が必要になることはめったにないということです。マッピング構成オプションを掘り下げて、あらゆる種類の複雑で単純なオブジェクトを作成します。アイデアは、必要なものすべてを取得することであり、多かれ少なかれ何も取得しません。

于 2012-04-11T21:56:01.130 に答える
22

あなたへの私の提案は、https://stackoverflow.com/questions/7499133/mapping-deeply-hierarchical-objects-to-custom-classes-using-knockout-mapping-plugで答えたのと同じ別の質問になります。

マッピングプラグインを使用する理由は合理的であり、私が使用しているものです。なぜ必要以上のコードを入力するのですか?

ノックアウトの経験(4か月すべて)では、手動で実行し、ノックアウトルーチンに実行させる回数が少ないほど、アプリの実行が向上するように見えることがわかりました。私の提案は、最初に最も単純なアプローチを試すことです。それがあなたのニーズを満たさない場合は、単純なアプローチがそれを「行う」ことをどのように行っているかを見て、あなたのニーズを満たすために何を変更する必要があるかを判断します。

于 2011-09-22T17:29:08.543 に答える
4

アレン、Knockout.jsでの最近の学習経験は、あなたの経験と似ています。サーバーからの深い階層オブジェクトグラフを使用して、その基本構造を保持する明示的なインスタンス化可能なビューモデル関数を定義しました。

私は、各プロパティを関連するビューモデルでオブザーバブルとして明示的に定義することから始めましたが、それはすぐに手に負えなくなりました。また、マッピングプラグインの使用に切り替える主な理由は、グラフをサーバーに頻繁にAjax投稿して、永続バージョンとマージし、サーバーで多数のプロパティを検証できるようにする必要があることです。変更とコレクションが変更され、新しいインスタンスがAjaxの結果として返され、クライアント表現と再マージする必要があります。これは非常に困難になり、マッピングプラグインは、追加/削除/更新を解決し、更新されたグラフを元のグラフに再マッピングするための識別子の指定を可能にすることで、大きな助けとなりました。

また、サブビューモデルの「作成」オプションを使用して、元のグラフの作成にも役立ちました。各ビューモデルコンストラクターで、親ビューモデルへの参照と、子ビューモデルを構築するためのデータを受け取り、渡された子データから孫を作成するためのマッピングオプションをさらに作成します。

この質問で詳しく説明されているように、最近見つけた唯一の(わずかな)欠点は、ko.mapping.toJSONを実行すると、プロパティを除外するためにビューモデルのプロトタイプで定義したtoJSONオーバーライドにフックされないことです。シリアル化から。その投稿でRyanNiemeyerが推奨しているように、マッピング解除で無視オプションを指定することで、これを回避することができました。

要約すると、私は間違いなくマッピングプラグインに固執します。Knockout.jsのルール。

于 2012-06-22T07:37:36.007 に答える
1

よりシンプルですが、ヘルプフルアドオンはノックアウトデータプロジェクションである可能性があります

現在、jsからviewmodelへのマッピングは処理しませんが、viewmodelからJSへのマッピングは非常にうまく処理します。

于 2012-04-24T10:40:01.913 に答える