在主干js中呈现视图时调用javascript。渲染后回调?
请看,主干视图渲染调用:在主干js中呈现视图时调用javascript。渲染后回调?,javascript,view,backbone.js,Javascript,View,Backbone.js,请看,主干视图渲染调用: render: function() { $(this.el).html(this.template({title: 'test'})); //#1 this.renderScatterChart(); return this; }, 因此,我将标准渲染称为#1。然后,我调用一个方法[这次,它是一个图表库的包装器]来查找div。但是在这一点上,它还没有连接到DOM(对吗?)。因此,图表调用不幸地死去 这种模式是什么?我希望听到有一个渲染后回调。我已经尝试
render: function() {
$(this.el).html(this.template({title: 'test'})); //#1
this.renderScatterChart();
return this;
},
因此,我将标准渲染称为#1。然后,我调用一个方法[这次,它是一个图表库的包装器]来查找div。但是在这一点上,它还没有连接到DOM(对吗?)。因此,图表调用不幸地死去
这种模式是什么?我希望听到有一个渲染后回调。我已经尝试过一些解决方法,有时我会让图表正常工作,但事件不会绑定。我通常的做法是在超时为零的情况下,一旦浏览器再次获得控制权,就安排一些事情发生。试试这个:
render: function() {
$(this.el).html(this.template({title: 'test'}));
var _this = this;
setTimeout(function() {
_this.renderScatterChart();
}, 0);
return this;
}
或者,如果renderScatterChart
已绑定到相应的,则此:
render: function() {
$(this.el).html(this.template({title: 'test'}));
setTimeout(this.renderScatterChart, 0);
return this;
}
如果您想更明确地了解自己的活动,也可以使用:
延迟延迟(函数,[*参数])
延迟调用函数,直到清除当前调用堆栈,类似于使用延迟为0的设置超时
所以你也可以这样做:
// Assuming that `renderScatterChart` is bound to the appropriate `this`...
render: function() {
$(this.el).html(this.template({title: 'test'}));
_(this.renderScatterChart).defer();
return this;
}
// or if it isn't bound...
render: function() {
$(this.el).html(this.template({title: 'test'}));
var _this = this;
_(function() {
_this.renderScatterChart();
}).defer();
return this;
}
您可以这样做(如果renderSactterChart在“jQuery-ized”对象上运行):
(这不是实际的DOM元素…与highcharts的问题相同。我使用的是Backbone.LayoutManager,最后修改了代码以添加postRender回调。我很想将此作为Backbone.js的一部分,这个问题已经得到了回答,但为了将来的参考,我已经遇到过好几次了。我通过添加自定义事件解决了这个问题,在本例中,它可能类似于
render: function() {
$(this.el).html(this.template({title: 'test'})); //#1
this.on('someView:append', function() {
this.renderScatterChart();
}, this);
return this;
}
然后,当我将元素附加到DOM中时,我会像
myView.trigger('someView:append');
现在,这肯定不是一个好的解决方案。您正在将触发此事件的责任添加到将渲染视图附加到DOM的任何内容中。取决于代码的结构,它可以更好或更差。再一次,我只是将此作为未来的参考和替代
更多信息:我知道答案是肯定的,但我想与大家分享一下。下划线js通过ux.defer函数为您提供了这一功能
render: function() {
$(this.el).html(this.template({title: 'test'})); //#1
_.defer( function( view ){ view.renderScatterChart();}, this );
return this;
},
根据下划线文档,这实际上与公认的解决方案相同。这是因为您在将.el插入DOM之前运行了render。检查我的自我解释代码(在包含Backbone.js的空白页中运行):
函数someThirdPartyPlugin(id){
if($('#'+id).length==0){
log(“插件崩溃”);
}否则{
log('嘿,不需要黑客!!!');
}
}
var SomeView=Backbone.View.extend({
id:'div1',
render:function(){
这个.el.append(“你好,第三方,我是主干网””;
一些第三方插件(这个$el.attr('id');
归还这个;
}
});
var SomeView2=Backbone.View.extend({
id:'div2',
render:function(){
这个.el.append(“你好,第三方,我是主干网””;
一些第三方插件(这个$el.attr('id');
归还这个;
}
});
var myView1=newsomeview();
$('body').append(myView1.render().el);
var myView2=newsomeview2();
$('body').append(myView2.el);
myView2.render();
如果您不想使用设置超时
黑客,我认为这种方式更“正常”:
只需将$el元素传递给需要操作通过render()
添加的元素的函数,然后就可以对$el执行DOM操作。应该这样做:
render: function() {
Marionette.ItemView.prototype.render.apply(this, arguments);
your code ...
}
木偶示例,但idea也适用于主干视图@whatbird:ThissetTimeout(…,0)
技巧只设置了一个函数,当JavaScript全部完成并且控件返回到浏览器时调用该函数。因此,您的代码将设置所有内容并将所有内容添加到DOM中,然后浏览器接管并触发延迟函数。这是一个技巧,但很有用。如果在运行render之前将view.el插入DOM,则不需要使用此技巧。我不喜欢使用setTimeout hack,遵循一个好的流,它是永远不需要的。检查我的答案,解释在插入前运行render.el和在插入后运行render.el的区别。一个运行崩溃,另一个正常工作,没有setTimeout攻击@DanielAranda:但这会迫使调用者了解视图的实现细节,并对视图执行非标准操作。因此,这是一个你想要哪种类型的乱七八糟(或者在当地情况下哪种可能)的问题。@muistooshort我同意你的观点,我知道在渲染之前插入视图的元素不是强制性的;我总是尽量避免使用setTimeout,在这种情况下,我知道问题与DOM注入有关,我分享了一个如何在不使用setTimeout黑客的情况下修复它的示例。这对我来说很有效,但让我觉得不干净。也许是主干。混合使用渲染覆盖将更好地集中在一个地方。
function someThirdPartyPlugin(id){
if( $('#' +id).length ===0 ){
console.log('Plugin crashed');
}else{
console.log('Hey no hacks needed!!!');
}
}
var SomeView = Backbone.View.extend({
id : 'div1',
render : function(){
this.$el.append("<p>Hello third party I'm Backbone</p>");
someThirdPartyPlugin( this.$el.attr('id') );
return this;
}
});
var SomeView2 = Backbone.View.extend({
id : 'div2',
render : function(){
this.$el.append("<p>Hello third party I'm Backbone</p>");
someThirdPartyPlugin( this.$el.attr('id') );
return this;
}
});
var myView1 = new SomeView();
$('body').append( myView1.render().el );
var myView2 = new SomeView2();
$('body').append( myView2.el );
myView2.render();
render: function() {
Marionette.ItemView.prototype.render.apply(this, arguments);
your code ...
}