我使用BackboneJS开发一个大型企业应用程序。应用程序中的一个页面是通过REsT使用多个子系统调用构建的。如何确保加载页面所需的所有服务都已被调用,并且模板绑定已完成?
例如,我有一个MasterView,它负责每个子视图的collection.fetch(),如下所示。3.
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]);
}
});
}
});我为页面设置了一个视图,它负责呈现另外两个视图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知道视图CustomerInfo和CustomerAccounts已经完成了渲染?这里我遇到的主要问题是CustomerInfo视图加载得很快,但是CustomerAccount视图需要一些时间才能加载。因此,当两个视图都在DOM上准备好时,我需要在一个快照上显示页面。
发布于 2013-05-17 00:44:58
在经历了相当长的一段时间后,我在谷歌上搜索,找到了this link。
所以我对我的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-09 19:12:52
实例化视图时,向view_ready事件添加一个侦听器。当视图完成获取数据和呈现时,让它在父视图的render方法的末尾触发它自己
self.trigger('view_ready');在主视图中添加如下内容:
this.listenTo(CustomerInfoView, 'view_ready', this.customer_info_ready);
this.listenTo(CustomerAccountsView, 'view_ready', this.customer_account_ready);然后,在主视图或主模型中添加两个属性: info_ready和customer_ready,并在每次触发前面提到的两个事件中的一个事件时将它们初始化为0,执行类似以下操作:
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');
}
}然后在主视图的'both_elements_ready‘中添加一个监听器:
initialize: function() {
//your code
this.on('both_elements_ready',this.page_ready); }编辑:添加信息,使答案与问题更相关,更详细。
发布于 2013-05-10 04:16:40
编辑:这个答案的灵感来自于我从一个示例“与卓别林共进午餐”示例here中学到的东西。Chaplin是一个建立在主干之上的框架。
好的,所以我将推荐一个基于coffeescript的解决方案(我恰好有一个解决方案在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 wanthttps://stackoverflow.com/questions/16455313
复制相似问题