1

私はノックアウトが初めてで、ノックアウトを使用してSPA(シングルページアプリケーション)を構築するためのシンプルなPOCを構築しています。

私がしたいのは、アプリがロードされたときに「ビジネスユニット」を表示し、ビジネスユニットを選択すると、そのビジネスユニットの下にすべての「フロントエンドユニット」が表示され、フロントエンドユニットを選択すると、その下にすべての「販売セグメント」が表示されることですそのフロントエンドユニット。

これはすべて、同じビューを使用する 1 つのページで行われ、viewmodel は選択されたビジネス ユニットまたはフロント エンド ユニットに基づいてモデルをバインドします。

私が直面している問題は、ドキュメントの準備ができたときに最初に適切にバインドされる 5 つのビジネス ユニットがありますが、ビジネス ユニットの選択時に、フロント エンド ユニットがそれぞれ 5 回繰り返されることです。この場合、2 つのフロント エンド ユニットがあり、それぞれが 5 回表示されます。フロントエンドユニットの選択についても同じ問題。

この問題は、次の jsFiddle サンプル - jsFiddle Linkで模倣されていることがわかります。

jsfiddle リンクにアクセスできない場合はお知らせください。このサンプルでは配列を使用しましたが、実際には oData サービスへの非同期呼び出しによってデータを取得します。

これはビュー HTML です。

<div id="divbu">
    <h4 data-bind="text: Heading"></h4>
    <ul data-role="listview" data-inset="true" data-bind="foreach: Collection">
        <li data-role="list-divider" data-bind="text: EntityName"></li>
                <li>
                    <a href="#" data-bind="click: $root.fnNextLevel">
                        <table border="0">
                            <tr>
                                <td>
                                    <label style="font-size: 12px;">Bus. Plan: </label>
                                </td>
                                <td>
                                    <label style="font-size: 12px;" data-bind="text: BusinessPlan"></label>
                                </td>
                                <td>
                                    <label style="font-size: 12px;">Forecast: </label>
                                </td>
                                <td>
                                    <label style="font-size: 12px;" data-bind="text: Forecast"></label>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <label style="font-size: 12px;">Gross Sales: </label>
                                </td>
                                <td colspan="3">
                                    <label style="font-size: 12px;" data-bind="text: GrossSales"></label>
                                </td>
                            </tr>
                        </table>
                    </a>
                </li>
            </ul>
</div>

これはモデルとビューモデルです:

function CommonModel(model, viewType) {
 var self = this;
 if (viewType == 'BU') {
     self.EntityName = model[0];
     self.BusinessUnit = model[0];
     self.BusinessPlan = model[1];
     self.Forecast = model[2];
     self.GrossSales = model[3];
 } else if (viewType == 'FEU') {
     self.EntityName = model[1];
     self.BusinessUnit = model[0];
     self.FrontEndUnit = model[1];
     self.BusinessPlan = model[2];
     self.Forecast = model[3];
     self.GrossSales = model[4];
 } else if (viewType == 'SS') {
     self.EntityName = model[2];
     self.BusinessPlan = model[3];
     self.Forecast = model[4];
     self.GrossSales = model[5];
 }

}

function ShipmentReportsViewModel(results, viewType) {

 var self = this;
 self.Collection = ko.observableArray([]);

 for (var i = 0; i < results.length; i++) {
     self.Collection.push(new CommonModel(results[i], viewType));
 }
 if (viewType == 'BU') {
     self.Heading = "Business Units";
     self.fnNextLevel = function (businessUnit) {
         FetchFrontEndUnits(businessUnit);
     };
     self.Home = function () {
         FetchBusinessUnits();
     };

 } else if (viewType == 'FEU') {

     self.Heading = results[0][0];
     self.fnNextLevel = function (frontEndUnit) {
         FetchSalesSegments(frontEndUnit);
     };
     self.Home = function () {
         FetchBusinessUnits();
     };
 } else if (viewType == 'SS') {
     self.fnNextLevel = function () {
         alert('No activity zone');
     };
     self.Heading = results[0][0] + ' - ' + results[0][1];
     self.Home = function () {
         FetchBusinessUnits();
     };
 }

}

完全なコードは jsFiddle リンクで確認できます。

また、要素 ID を指定してバインディングを適用する複数のビューと複数のビュー モデルでこれを試しました。この場合、ビジネス ユニット -> 販売セグメントからの 1 つのフローは問題ありませんが、ホームまたは戻るボタンをクリックしてその要素に再度バインドすると、同じ問題に直面します。(ホームと戻るボタンの機能は、jsFiddle の例では行われません)。

詳細が必要な場合はお知らせください。スタックオーバーフローの他の多くのリンクを調べましたが、この特定の問題に対処するものは何もありません.

どんな助けでも大歓迎です。前もって感謝します。

4

2 に答える 2

3

ここでの問題は、ko.applybindings を 2 回呼び出し、5 つの項目内で反復する foreach バインディングがあるため、データが 5 回複製されることです。

同じモデルで ko.applybindings を複数回呼び出すべきではありません。パラメータ化されていても、モデルは常に同じです。

ここでも同じ問題がありました: ObservableArray からのデータがテーブルに 2 回表示されます

viewModel 内にビジネス ロジックがあるという事実は議論の余地があり、これを修正するのは簡単ではありません。

3 つのクラスを作成し、内部にロジックを持たない共通モデルに配置します。次に、ko.applyBindings を 1 回適用したら、次のように配列を変更するだけです。

viewModel.myArray(newValues)

修正されたコードのフィドルは次のとおりです。http://jsfiddle.net/MaurizioPiccini/5B9Fd/17/ 必要なことを正確に行うことはできませんが、 Collection オブジェクトのスコープをモデルの外に移動して複数のバインディングを削除する場合。ご覧のとおり、同じモデルで ko.applybindings を 2 回呼び出していることが問題です。

于 2013-06-10T09:07:27.137 に答える
0

最後に、私はこれを機能させました。@MaurizioIndenmark に感謝します。

ko.applybindings の複数の呼び出しを削除しましたが、まだビュー モデルを複数回呼び出していました。これが問題の原因でした。

これで、ビュー モデルがきれいになり、さまざまなアクションに対してさまざまな関数呼び出しがあり、これらの関数 (イベント) 内で変更する必要があるすべてのデータを変更します。現在、すべてが期待どおりに機能しています。

これは、ビューモデルが現在どのように見えるかです -

function ShipmentReportsViewModel(results) {
var self = this;
self.Heading = ko.observable();
self.BusinessUnits = ko.observableArray();
self.FrontEndUnits = ko.observableArray();
self.SalesSegments = ko.observableArray();

self.Home = function () {
    var bu = FetchBusinessUnits();
    self.Heading("Business Units");
    self.BusinessUnits(bu);
    self.FrontEndUnits(null);
    self.SalesSegments(null);
};
self.fnFeu = function (businessUnit) {
    var feu = FetchFrontEndUnits(businessUnit);
    self.Heading(feu[0].BusinessUnit);
    self.FrontEndUnits(feu);
    self.BusinessUnits(null);
    self.SalesSegments(null);
};
self.fnSalesSeg = function (frontEndUnit) {
    var ss = FetchSalesSegments(frontEndUnit);
    self.Heading(ss[0].BusinessUnit + ' - ' + ss[0].FrontEndUnit);
    self.SalesSegments(ss);
    self.BusinessUnits(null);
    self.FrontEndUnits(null);
};
self.Home();
}

動作するソリューション全体を確認するには、このjsFiddleを参照してください

この作品を手に入れるためのすべての貴重な提案に感謝します。

于 2013-06-24T08:20:52.730 に答える