我遇到的问题是我的父视图的render()方法在其子render()方法完成之前返回。
所以我在Backbone路由器中进行了这些调用:
this.viewState.get('headerView').render();
this.viewState.get('mainView').render();
this.viewState.get('footerView').render(); //this function starts (and completes) before the above completes
问题是在mainView呈现之前页脚呈现,因为主视图render()函数在mainView的子视图完成呈现到DOM之前完全返回。因此,当页脚插入DOM时屏幕会闪烁,然后当mainView实际渲染时页脚会被按下。
我喜欢在Backbone视图的render()函数中使用“return this”的范例,但我能想到解决这个问题的唯一方法是使用异步库或其他东西链接render()函数,使用异步/ CPS回调。
所以,我将这段代码作为Backbone View的渲染函数的一部分:
//这里父母呈现它的子视图:
function renderChildren($template) {
var ret = EJS.render($template, {
users: data
});
this.$el.html(ret); //***
this.childLoginView = new LoginView({el: this.$('#child-view-login-container')});
//console.log('this.childLoginView.$el', self.childLoginView.$el);
this.childLoginView.render();
this.childLoginView.delegateEvents();
this.childRegisteredUsersView = new RegisteredUsersView({el: this.$('#child-view-registered-users-container')});
//console.log('this.childRegisteredUsersView.$el', self.childRegisteredUsersView.$el);
this.childRegisteredUsersView.render();
this.childRegisteredUsersView.delegateEvents();
console.log('IndexView rendered');
}
我可以告诉你一个事实,即在子视图实际渲染之前记录了“IndexView rendered”。这当然意味着子渲染函数是异步的,这也意味着只有在父视图的渲染方法完成后才渲染子视图,网页才会闪烁。
就像我说的,这表明render()方法确实是异步的。所以我想一次渲染一个视图,这样页面就不会闪烁 - 这是一个合理的想法吗?希望Web视图上的闪烁更少,因为事情只是连续呈现,但我不知道如何做到这一点。
关于***的行。有没有办法为父视图定义模板,并且只有在子视图渲染之后,才能使用.html()将模板插入到DOM中?这可能需要回调,在这种情况下,不可能从父视图的render()函数中“返回”。
答案 0 :(得分:1)
您的view.render()
中可能有一些异步操作导致竞争条件。
使用$.Deferred();
:
render: function () {
var self = this,
dfd = $.Deferred();
this.model.fetch({
succcess: function (response) {
// do here the operations on your cached DOM:
self.$el.append(response.model.models);
dfd.resolve({template: self.$el});
}
});
return dfd.promise();
}
现在您可以控制渲染方法的顺序:
$.when(viewState.get('headerView').render()).then(function(result) {
$('body').append(result.template);
viewState.get('mainView').render().then(function (result) {
$('body').append(result.template);
});
});
这将一次渲染一件。当承诺得到解决时,用户将看到屏幕的新部分出现。
看到这个小提琴:https://jsfiddle.net/h0h888rm/2/
如果你想等到每个渲染完成并只重新加载一次parentView,那么请考虑这个替代解决方案:
如果您希望渲染器以异步方式运行,但仅在完成所有渲染时才执行parentView渲染,请执行以下操作:
$.when(
viewState.get('headerView').render(),
viewState.get('mainView').render()
).then(function (result1, result2) {
$('body').append(result1.template)
.append(result2.template);
});