2012-06-28 4 views
5

MVVMベースのシングルページアプリケーションを実装しようとしていますが、MVVMのviewmodel/view部分を処理するためにフレームワークKnockout.jsを現在使用しています。私は混乱しています。ノックアウトを実装するために私が見てきたすべての例は、ビューモデル全体をデータベースに保存することを含みます。これらの例では、ビューモデルがデータレイヤーモデルと同期し、モデルが検証/サーバー同期を行う「モデル」ステップがありません。MVVM with Knockout.js

1つのページに複数の異なるテンプレート/ビューをそれぞれ別のビューモデルで作成したいと考えています。私が見つけたもう一つのことは、knockout.jsが異なるビュー間で単一のモデル(ビューモデルではない)を同期させていることです。すべてのビューが共有する1つの巨大なビューモデルを持つのは意味がないと思うので、各ビューには独自のビューモデルがあると考えていましたが、各ビューモデルは必要なアプリケーション規模のモデル各ビュー。

私が取り組んでいるページは、巨大なモデル(30以上のフィールド、親子関係の複数のレイヤー)を取得しています。私はすべてのビューモデルをこのモデルと同期させるのが理にかなっていると思います。私はknockout.js(knockout.jsとbackbone.jsを組み合わせたもの)を調査しましたが、ページがAPIからデータを取得しているので、fetch、set、saveなどの関数の大部分を書き直しました。モデル全体をサーバと前後に同期させるだけなので)、私はそれに反対して決めました。私のアプリケーションの

視覚的な例:

(モデル層) M | M

(ビューモデル/ビューレイヤー)VM-V | VM-V | VM-V | VM-V


例モデルはユーザー=あろう

別の例{firstNameの "最初" とLastName: "最後"、...}

1のviewmodelのみファーストネームが必要であり、別のviewmodelのみ姓を必要
ViewModelA = {firstNameの:app.User.firstName()}
ViewModelB = {firstNameの:app.User.lastName()}

モデルとビューモデルの変更のためのpub/subシステムを定義するためにこれを行う唯一の方法はありますか?これは良い/維持可能なアーキテクチャですか?ここに基本的なコンセプトがないのですか?すべてのアドバイスは大歓迎です

答えて

5

これを正しく読めば、ノックアウトでMVVM/SPAを構築する方法に焦点を当てた多くの質問がここにあります。あなたが指摘したように、取り組むべきことがいくつかあります。 1つは、ビューモデルとビューのペア間で通信する方法です。

マスターViewModel これを行うには、@Tyrsiusの回答としてマスターviewmodelを使用する方法があります。あなたのシェルはより多くの利用可能なデータをバインドするビューモデルを持つことができます。マスタービューモデルは、子ビューモデルもオーケストレーションできます。このルートに行く場合は、外部シェルをマスターviewmodelに、内側のものをDOMの特定のHTML要素にバインドするように注意する必要があります。マスタビューモデルは、必要であれば、それらの間の通信を容易にすることができる。

減結合ビュー/ ViewModelにペア 別のオプションは、のviewmodel /ビューのペアなしマスターのviewmodelを使用することです。各ビューは、DOMの領域にロードされ、独自の領域にバインドされます。彼らは別々の単位として行動し、お互いから切り離されます。 pub/subを使って話をすることができますが、必要なのは観測データを介してデータを同期させる方法であれば、Knockoutには多くのオプションがあります。私が好きなのは、各ビューモデルのサーフェスモデルオブジェクトを持つことです。したがって、ビューには、ビューに固有の(モデルからの)データを表示するビューモデルがあります。非常に多くのビューモデルは、同じモデルをさまざまな方法で表示できます。したがって、ビューが(モデル内の)viewmodelプロパティを更新すると、同じモデルを使用する他のロードされたビューモデルに波及します。

DataContext さらに進んで、モデルのデータを管理するdatacontextモジュールを作成することができます。 datacontextにモデル(例:顧客のリスト)とdatacontextのチェックがあるかどうかを確認します。もしそうでなければ、ajax呼び出しから取得します。どちらの方法も、ビューモデルとモデルから抽象化されています。 datacontextはデータを取得し、モデルをviewmodelに返します。このように、あなたは非常に分離されていますが、datacontextを介してデータ(あなたのモデル)を共有することができます。

私は続けていくことができますが、これがあなたの質問に答えるかどうか教えてください。そうでない場合は、他の詳細に答えてください。

**免責事項:私は

+0

+1パブ/サブを言及するために+1、私はそれを言及することを忘れました。 – Tyrsius

+0

まずは遅れていたJohnと@Tysiriusの返事をおかけして申し訳ありませんが、私は先週別のプロジェクトに参加しました。 私はあなたが提案しているDecoupled V/VM構造が本当に好きです。私は、あなたがSPAで "ページ"をどのようにしていても、全体的なモデルが永続するという考えが好きです。 私はそれを解釈すると、10個のフィールド(今はすべてko.observable())を持つモデルがあり、そのモデルの部分表現と同期する複数のビューモデル(いくつかのフィールドのみ)、そして「波紋」はすばらしく働いています。 –

+0

それはあなたのために働くのがうれしいです。その実パターンIMO。 –

2

これは現在注目されている分野ですので、より良い回答が得られると期待していますが、ここにはあります。

モデル

はい、あなたは絶対にあなたのモデルであり、データのサーバー側の表現を、持っている必要があります。これはあなたのサーバーとデータベースによって異なります。 MVC3の場合、これはあなたのエンティティモデルです。 DjangoやRubyの場合、DBの設定の一部としてdbモデルが定義されています。この部分は特定の技術に依存します。しかし、agian、はいあなたはモデルを持っている必要があり、サーバーは絶対にデータ検証を行う必要があります。

アプリケーション(ViewModelには)

あなたの意見それぞれ独自のviewmodelを持っていることをお勧めします。あなたのページには、ViewModelもあります。App ViewModelなら、そのすべてを追跡できます。このルートに進むと、ビュー間の切り替えや他のアプリケーションレベルのロジック(ハックバッドナビゲーション、他の一般的なシングルページツールなど)の実装がアプリのビューモデルによって管理されます。この階層は非常に重要ですが、必ずしも単純ではありません。それはあなたのアプリケーションの特定の要件になります。あなたはフラットなビューモデルに限定されません。唯一可能な方法ではありません。

アドホック例:

​var ThingViewModel = function(name, data){ 
    this.name = ko.observable(name); 
    //Additional viewmodel stuffs 
}; 

var AppViewModel = function(initialData){ 
    //Process initial data  
    this.thing = new ThingViewModel(someName, someData); 

}; 

あなたが見てみましょうしたい場合、私は、here on GitHubを主催している、純粋な研究(ない現実世界のアプリ)のために、今、似たようなプロジェクトに取り組んでいますいくつかの本当のexmaples。現在devブランチは、現時点ではmasterブランチよりかなり先にあることに注意してください。私はそれにいくつかの悪いパターンが含まれていると確信しています(それらを指摘自由に感じ、私も学んでいる)が、とにかくそれからいくつかのことを学ぶことができるかもしれません。

+0

こんにちは! - あなたは "あなたは絶対にデータのサーバー側の表現を持っているべきです"というあなたの意見は、あなたのビューモデルへの各変更が最初にサーバー経由で行われることを意味しますか? – MikeW

+0

絶対にありません!私は、サーバーがこのデータ(通常はデータベース)を保持しており、サーバーがそれを処理しなければならないため、モデルクラスがサーバー上に存在する必要があるということでした。ノックアウトビューモデルの操作は、可能な限りクライアント*にとどまるべきです*。 – Tyrsius

1

:-)(ノックアウトとこの戦略を使用して)SPAの上Pluralsightコースを構築しています私はウェブ版にWPFアプリケーションを再加工していたにも同様に複雑なソリューションを持っています。 WPFバージョンは、プレゼンターモデルを使用してビューにバインドされた複雑なドメインオブジェクトを扱いました。

ウェブ版では、Automapperを使用してドメインオブジェクトとの間で前後に翻訳される、簡略化されたやや平坦なサーバーサイドビューモデルを実装しました。次に、これらのサーバー側のビューモデルはJSONとしてクライアントに送られ、マッピングプラグインを使用して対応するKnockoutビューモデル(サブマッピングオプションを使用して子を作成するためのインスタンス化可能な関数)にマッピングされます。

私のUIを保存/検証する必要があるとき、ノックアウトビューモデルの全部または一部をプレーンなJavascriptオブジェクトにマップしてJSONとしてポストし、MVCフレームワークはそれをサーバー側のビューモデルAutomappedをドメインオブジェクトに戻し、ドメインレイヤーによって検証され、場合によっては更新された後、修正された完全グラフまたは部分グラフが返され、再マッピングされます。

現在のところ、ノックアウトアクションが行われるメインページは1つしかありませんが、あなたと同じように、同じモデル(ドメインオブジェクト)を扱う必要のある複数のコンテキストが異なるビューモデルとして取り込まれることが予想されます私がそれらと何をしているかによって。

私はノックアウトビューモデルの構造だけでなく、これを予期してサーバー側のビューモデルのディレクトリなどを構造化しました。これまでのところ、このアプローチはうまく機能しています。お役に立てれば。

+0

この回答をいただきありがとうございます。私はまだJSONマッピングを開始していませんが、これは便利だと思います! –

0

プロジェクト中に、デカップリングされたView/ViewModelペアを提供し、ビュー内でサブビューをインスタンス化できるフレームワーク(KnockoutJSを使用する)を開発しました。ビューとサブビューインスタンシエーションの全体の処理は、フレームワークによって提供されます。 WPFのMVAMとXAMLのように機能します。

見てくださいhttp://visto.codeplex.com