1

BackboneJS を使用して大規模なエンタープライズ アプリケーションに取り組んでいます。アプリケーション内の 1 つのページは、REST を介した複数のサブシステム コールを使用して構築されます。ページをロードするために必要なすべてのサービスが呼び出され、テンプレートがバインドされていることを確認するにはどうすればよいですか?

たとえば、次のように、各子ビューを  MasterView処理する があります。collection.fetch()

myApp.views.MasterView = Backbone.View.extend({
    initialize: function(params) {
        var self = this;
        this.collection.fetch({
            success: function(resp) {
                self.collection.bind("reset", self.render(), self);
            },
            error: function(xhr, xhrStatus) {
                // push error message, in case of fetch fails.
            }
        });
    },
    render: function() {
        var self = this;
        this.collection.each(function(model) {
            if (model.get('authorize') && model.get('status') === "success" && model.get('data').length > 0) {
                self.bindTemplate(model.get('data')[0]);
            }
        });
    }
});

このページには、他の 2 つのビュー CustomerInfo と CustomerAccounts のレンダリングを処理するビュー セットがあります。ビューはこのようになります。

myApp.views.CustomerView = Backbone.View.extend({
        initialize: function() {
            var customerInfo = new myApp.collection.CustomerInfo();
            new myApp.views.CustomerInfo({el: $("#infoContainer"), collection: customerInfo});

            var customerAccount = new myApp.collection.CustomerAccount();
            new myApp.views.CustomerAccount({el: $("#accountContainer"), collection: customerAccount});
        }
});

  また、CustomerInfo および CustomerAccount ビューは次のようになります。  

myApp.views.CustomerInfo = myApp.views.MasterView.extend({
    initialize: function() {
        var self = this;
        myApp.views.MasterView.prototype.initialize.call(self, {
            qParam1: "qparam1",
            qParam2: "qparam2"
        });
    },
    render: function() {
        var self = this;
        self.template = _.template(myApp.Templates.get("customer-page/customer-info"));
        myApp.views.MasterView.prototype.render.apply(self);
    },
    bindTemplate: function(data) {
        var self = this;
        $(self.el).html(self.template({"info": data}));
    }
});
 
myApp.views.CustomerAccounts = myApp.views.MasterView.extend({
    initialize: function() {
        var self = this;
        myApp.views.MasterView.prototype.initialize.call(self, {
            qParam1: "qparam1"
        });
    },
    render: function() {
        var self = this;
        self.template = _.template(myApp.Templates.get("customer-page/customer-accounts"));
        myApp.views.MasterView.prototype.render.apply(self);
    },
    bindTemplate: function(data) {
        var self = this;
        $(self.el).html(self.template({"accounts": data}));
    }
});

myApp.views.CustomerViewビューCustomerInfoCustomerAccountsそのレンダリングが完了し  たことを から知る方法があるかどうか知りたいですか? ここで私が抱えている主な問題は、CustomerInfoビューの読み込みが速いことですが、ビューの読み込みにCustomerAccount時間がかかることです。したがって、DOM で両方のビューの準備ができたら、ページを一度に表示する必要があります。

4

3 に答える 3

0

しばらく頭を悩ませ、Googleで検索した後、このリンクを見つけました。

そのため、MasterViewにいくつかの変更を加えましたが、機能していて、問題を解決しました。MasterViewで行った変更はこれです

var activeConnections=0;

myApp.views.MasterView = Backbone.View.extend({
    initialize: function(params) {

        activeConnections++;

        var self = this;
        this.collection.fetch({
            success: function(resp) {

                activeConnections--;

                self.collection.bind("reset", self.render(), self);

                if(activeConnections===0){
                    // trigger the page has finished rendering
                }
            },
            error: function(xhr, xhrStatus) {
                // push error message, in case of fetch fails.
                if(activeConnections===0){
                    // trigger the page has finished rendering
                }
            }
        });
    },
    render: function() {
        var self = this;
        this.collection.each(function(model) {
            if (model.get('authorize') && model.get('status') === "success" && model.get('data').length > 0) {
                self.bindTemplate(model.get('data')[0]);
            }
        });
    }
});

これを解決するのを手伝ってくれたすべての人に感謝します。

于 2013-05-16T16:44:57.500 に答える
0

When you instantiate your views add a listener to a view_ready event. When the view finishes fetching the data and rendering make it trigger it on itself At the end of the render method of the parent view

self.trigger('view_ready');

And on the Main view add something like :

this.listenTo(CustomerInfoView, 'view_ready', this.customer_info_ready);
this.listenTo(CustomerAccountsView, 'view_ready', this.customer_account_ready);

Then in your main view or main model add 2 properties : info_ready and customer_ready and initialize them to 0 Each time one of the 2 previously mentioned event is fired do something like the following :

customer_info_ready : function(){
    this.model.set('info_ready',true);
    if (this.model.get('account_ready') === true) {
         this.trigger('both_elements_ready'); 
     }
}
customer_account_ready : function(){
    this.model.set('account_ready',true);
    if (this.model.get('info_ready') === true) {
         this.trigger('both_elements_ready'); 
     }
}

Then add a listener to 'both_elements_ready' on your main view :

initialize: function() { 
 //your code
 this.on('both_elements_ready',this.page_ready); }

EDIT: Added info to make answer more relevant to question and more detailed.

于 2013-05-09T11:12:51.893 に答える
0

編集:この回答は、サンプル「チャップリンとのブランチ」の例から学んだことから着想を得ていますチャップリンは、バックボーンの上に構築されたフレームワークです。


わかりましたので、coffeescript ベースのソリューションを提案します (たまたまコーヒーにソリューションがあります :/ ! js に戻す場合は、js2coffeeを使用してみてください)。

マスタークラス

アイデアは、マスター ビューの代わりにアプリを手に保持するマスター クラス (ビューではなく) を持つことです。

module.exports = class Application
  initialize: (finished_init) =>
    @collection = new Collection()
    @main_view = new View()
    @collection.fetch(
      success: (collection) =>
        @main_view.collection = @collection
        finished_init()
    )
  render: (targetLocation, params) ->
    switch targetLocation
      when "main" then (
        @main_view.render()
      )

このinitializeメソッドでは、コレクション データをフェッチします。成功すると、finshed_init()が呼び出されます。@render(Btw, @== this :) )に置き換えることができます

初期化

アプリを初期化する方法は次のとおりです。

$ ->
  app = new Application()

  app.initialize( ->
    #----------------------------------#
    # Create the router and its routes
    # This is called at the finished_init() of the Application class
    #----------------------------------#
    app_router = new Router
  )

複数のfetche非同期実行

fetche の完了を監視する関数を用意するか、 asyncを使用してみてください。それを実現する素晴らしい`parallel機能があります。

@collection1 = new Collection()
@collection = new Collection()
@main_view1 = new View()
@main_view2 = new View()

async.parallel [ (callback) ->
  setTimeout (->
    @collection1.fetch(
      success: (collection) =>
        @main_view1.collection = @collection
        callback null, "one"
  ), 200
, (callback) ->
  setTimeout (->
    @collection2.fetch(
      success: (collection) =>
        @main_view2.collection = @collection
        callback null, "two"
  ), 100
 ], (err, results) ->
   if not err
    @render()  # Render what you want
于 2013-05-09T20:16:40.197 に答える