在 BackBone js 中调用 javascript 渲染视图。渲染后回调?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9145680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 05:43:51  来源:igfitidea点击:

calling javascript on rendering views in BackBone js. post-render callback?

javascriptviewbackbone.js

提问by whatbird

behold, a backbone view render call:

看,一个主干视图渲染调用:

render: function() {
  $(this.el).html(this.template({title: 'test'}));  //#1
  this.renderScatterChart();
  return this;
},

so, I call a standard render at #1. and then, i call a method [this time, it is a wrapper for charting lib] that looks for a div. the div is rendered by the render call. but at this point, it is not attached to the DOM yet (right?). so the chart call sadly dies.

所以,我在 #1 处调用了标准渲染。然后,我调用一个方法 [这一次,它是一个用于绘制 lib 图表的包装器] 来寻找一个 div。div 由渲染调用渲染。但此时,它还没有附加到 DOM 上(对吧?)。所以图表调用可悲地死了。

what is the pattern for this? i'd love hear that there is a post-render callback. i've tried a few hacks around this, and sometimes i get the chart to work, but events don't bind.

这是什么模式?我很想知道有一个渲染后回调。我已经尝试了一些解决这个问题的技巧,有时我让图表工作,但事件没有绑定。

回答by mu is too short

My usual approach for this sort of thing is to use setTimeoutwith a timeout of zero to arrange for something to happen once the browser gets control again. Try this:

我对这类事情的常用方法是使用setTimeout零超时来安排浏览器再次获得控制权后发生的事情。试试这个:

render: function() {
    $(this.el).html(this.template({title: 'test'}));

    var _this = this;
    setTimeout(function() {
        _this.renderScatterChart();
    }, 0);

    return this;
}

Or, if renderScatterChartis already bound to the appropriate this:

或者,如果renderScatterChart已经绑定到适当的this

render: function() {
    $(this.el).html(this.template({title: 'test'}));
    setTimeout(this.renderScatterChart, 0);
    return this;
}

You can also use _.deferif you want to be more explicit about what you're up to:

您也可以使用_.defer,如果你想更明确的了解你在做什么:

defer_.defer(function, [*arguments])

Defers invoking the functionuntil the current call stack has cleared, similar to using setTimeoutwith a delay of 0.

推迟_.defer(function, [*arguments])

推迟调用函数,直到当前调用堆栈已清除,类似于使用延迟为 0 的setTimeout

So you could also do it like this:

所以你也可以这样做:

// 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;
}

回答by Xesued

I know this is answered, but thought I would share. Underscore js has this covered for you with the _.defer function.

我知道这是回答,但我想我会分享。Underscore js 用 _.defer 函数为你解决了这个问题。

render: function() {
    $(this.el).html(this.template({title: 'test'}));  //#1
    _.defer( function( view ){ view.renderScatterChart();}, this );
    return this;
},

According the the Underscore docs, this is effectively the same thing as the accepted solution.

根据 Underscore 文档,这实际上与公认的解决方案相同。

回答by Daniel Aranda

It is because you run render before .el is inserted into the DOM. Check my self explanatory code(run in a blank page with Backbone.js included):

这是因为您在 .el 插入到 DOM 之前运行渲染。检查我的自我解释代码(在包含 Backbone.js 的空白页面中运行):

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();

回答by dotslashlu

If you don't want to use the setTimeouthack, I think this way is more 'normal':

如果您不想使用setTimeouthack,我认为这种方式更“正常”:

Just pass the $el element to the function that needs to manipulate elements added by render()and then DOM manipulation can be done on $el.

只需将 $el 元素传递给需要操作添加元素的函数,render()然后就可以对 $el 进行 DOM 操作。

回答by Andy

You could just do this (if renderSactterChart operates on a 'jQuery-ized' object):

您可以这样做(如果 renderSactterChart 对“jQuery 化”对象进行操作):

render: function() {
  this.$el.html(this.template({title: 'test'}));  //#1
  this.$el.renderScatterChart();
  return this;
},

(this is not the actual DOM element...)

(这不是实际的 DOM 元素...)

回答by Shreyas

Had the same problem as you did...with highcharts. I was using Backbone.LayoutManager, and ended up hacking the code to add a postRender callback. Would love to see this as a part of Backbone.js

和你有同样的问题......使用 highcharts。我正在使用 Backbone.LayoutManager,并最终破解了代码以添加 postRender 回调。希望将其视为 Backbone.js 的一部分

回答by julioolvr

Well this has already been answered, but for future reference I've had this problem a few times. I solved it by adding custom events, in this case it could be something like

嗯,这已经得到了回答,但为了将来参考,我遇到过几次这个问题。我通过添加自定义事件来解决它,在这种情况下它可能类似于

render: function() {
  $(this.el).html(this.template({title: 'test'}));  //#1

  this.on('someView:append', function() {
      this.renderScatterChart();
  }, this);

  return this;
}

And then, when I append the element to the DOM, I trigger it like

然后,当我将元素附加到 DOM 时,我会像这样触发它

myView.trigger('someView:append');

Now, it's certainly not a beatiful solution. You are adding the responsability of triggering this event to whatever is appending the rendered view to the DOM. Depending on how is your code structured it can fit better or worse. Again, I'm just posting this as a future reference and alternative.

现在,这肯定不是一个完美的解决方案。您正在将触发此事件的责任添加到将呈现的视图附加到 DOM 的任何内容。根据您的代码的结构方式,它可以更适合或更差。同样,我只是将其发布为将来的参考和替代方案。

More info: http://backbonejs.org/#Events

更多信息:http: //backbonejs.org/#Events

回答by user2846569

This should be done like so:

这应该像这样完成:

render: function() {
  Marionette.ItemView.prototype.render.apply(this, arguments);
  your code ...
}

sample with marionette but idea works for backbone views as well

带有牵线木偶的示例,但想法也适用于主干视图