1

Durandal 2.0 でアプリケーションを構築しています。
私のシェルビューは次のようになります。

<div>
    <header id="nav" data-bind="compose: 'viewmodels/nav', activate: false">
    </header>
     <section id="content" class="main container-fluid" data-bind="router: { transition: 'entrance' }, activate: false" style="overflow: auto">
     </section>
    <footer>
        <!--ko compose: {view: 'footer'} --><!--/ko-->
    </footer>
</div>

nav セクションには、タブとユーザーのドロップダウン リストを表示したいと考えています (どちらも Web サービスから取得されます)。ドロップダウンからユーザーを選択すると、コンテンツ セクションを更新する新しい URL に移動します。 (ルートは localhost/#user1/tab2 のようになります)。

  • 問題: コンテンツ セクションのデータを取得する前に、ナビゲーション セクションから選択したユーザーを知る必要がありますが、ユーザーを取得する前にコンテンツ セクションがアクティブになっています。

ユーザー リストは 1 回しか取得されないため、これは実際には最初のページ ロードのみの問題です。

  • ナビゲーション セクションの読み込みが完了するまでコンテンツ セクションに待機するように指示する方法はありますか?
  • 私がやっていることよりも、これを行うためのより良い方法はありますか?

nav activate 関数は次のようになります。

function activate(context) {        
    return dataservice.getUsers().then(function () {
        //do stuff
    });
}); 

この activate 関数が最初に呼び出され、dataservice.getUsers() が呼び出されますが、その後、コンテンツ モジュールの activate 関数が呼び出されてから、"do stuff" 部分が発生します (そして、getUsers 呼び出しからのデータが dataservice に返される前に)。 . 私の約束に問題があるのでしょうか?

編集
私が話していることを示すいくつかの実際のコードで dFiddle をまとめました: http://jerrade.github.io/dFiddle-2.0/#test/dashboard
コードはここにあります: https://github. com/jerrade/dFiddle-2.0

nav.js

 function activate(context) {
     console.log('Nav View Activated');
     if (vm.impersonateUsername == undefined)
         vm.impersonateUsername = getUsernameFromWindowLocation();

     return dataservice.getPageDetailForEmployee(vm.loggedInUsername, vm).then(function () {
         console.log("Page details retrieved");

         // I want to do something here before the dashboard activates.
     });
  }

ダッシュボード.js

 function activate(username) {
        console.log('Dashboard View Activated');
        //vm.username = nav.selectedImpersonateEmployee().Username;        
        return dataservice.getDashboard(nav.impersonateUsername, dashboard);
    }

ページを開き、コンソールを確認します。あなたは見るでしょう(とりわけ)

Nav View Activated  
Dashboard View Activated  
Page details retrieved 

私が本当に望んでいるのは、ダッシュボード ビューがアクティブになる前にページの詳細を取得することです。これが現在はもう問題にならないように、私は実際に物事を再調整しましたが、将来的に再びトリミングされる可能性があります.

私がやろうとしていることは、これほど複雑であるべきではないようです。ここの丸い穴に四角いペグを打ち込まない限り?

4

1 に答える 1

0

最も簡単なisUserLoaded方法は、ビュー モデルのようなものと呼ばれるオブザーバブルを追加することです。次に、ifコンテンツ セクションにバインディングを適用します。

<div>
    <header id="nav" data-bind="compose: 'viewmodels/nav', activate: false">
    </header>
    <!-- ko if: isUserLoaded -->
     <section id="content" class="main container-fluid" data-bind="router: { transition: 'entrance' }, activate: false" style="overflow: auto">
     </section>
    <!-- /ko -->
    <footer>
        <!--ko compose: {view: 'footer'} --><!--/ko-->
    </footer>
</div>

ユーザーをロードしたら、オブザーバブルを に更新するtrueと、コンテンツ バインディングが起動するはずです。

編集

それでもうまくいかない場合は、ルーターがまだコンテンツ ビュー モデルを解決している必要があるようです (これは、ルーティングの問題を示している可能性があります。解決策全体を見ずに言うのは難しいです)。

とにかく、ルーティングの問題でない場合は、コンテンツ モデルが activate メソッドから未解決の promise を返すソリューションを採用できます。次に、ユーザーがロードされたときにその約束を解決します。たとえば、次のようなものです。

userModel.js:

define([], function () {
    // single instance to track the loaded user
    var userModel = {
        selectedUser: ko.observable()
    };

    return userModel;
});

navModel.js:

define(["dataService", "userModel"], function(dataService, userModel) {
    // view model for the nav bar
    var navModel = {        
        // model definition
    };

    // load the user
    navModel.activate = function() {
        return dataService.getUsers().then(function(response) {
            // Push the user to the userModel
            userModel.selectedUser(response.user);
        });
    };

    return navModel;
});

contentModel.js:

define(["userModel"], function (userModel) {
    var contentModel = {
        // model definition
    };

    contentModel.activate = function () {
        // Prevent activation until user is resolved
        var deferred = $.Deferred();

        var subscription = userModel.selectedUser.subscribe(function (user) {
            if (!user)
                return;

            subscription.dispose();
            deferred.resolve();
        });

        return deferred.promise();
    };

    return contentModel;
});

プロパティにオブザーバブルを使用したくない場合は、userModel.selectedUser代わりに別の deferred を使用するか、ユーザーがロードされたときにイベントを発生させることができます。

于 2013-11-12T00:41:15.800 に答える