Подтвердить что ты не робот

Вызов javascript при просмотре представлений в BackBone js. обратный вызов после рендера?

Вот, вызов рендеринга позвоночника:

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

поэтому я называю стандартный рендер в # 1. и затем я вызываю метод [на этот раз, это оболочка для построения диаграммы lib], которая ищет div. div обрабатывается вызовом рендеринга. но на данный момент он еще не привязан к DOM (правильно?). так что графический вызов печально умирает.

Каков шаблон для этого? Мне бы очень хотелось услышать, что есть обратный вызов post-render. Я пробовал несколько хаков вокруг этого, и иногда я получаю диаграмму, чтобы работать, но события не связываются.

4b9b3361

Ответ 1

Мой обычный подход для такого рода вещей заключается в использовании setTimeout с тайм-аутом нуля, чтобы организовать что-то, что произойдет после браузера снова получает контроль. Попробуйте следующее:

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

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

    return this;
}

Или, если renderScatterChart уже привязан к соответствующему this:

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

Вы также можете использовать _.defer, если хотите более четко узнать, что вы делаете:

отложить _.defer(function, [*arguments])

Заблокирует вызов функции до тех пор, пока текущий стек вызовов не будет очищен, подобно использованию setTimeout с задержкой 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;
}

Ответ 2

Я знаю, что это ответ, но я подумал, что поделюсь. Подчеркнутый js имеет это для вас с помощью функции _.defer.

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

Согласно документам Underscore, это фактически то же самое, что и принятое решение.

Ответ 3

Это потому, что вы запускаете рендер, прежде чем .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();

Ответ 4

Вы могли бы просто сделать это (если renderSactterChart работает с объектом jQuery-ized):

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

(это не фактический элемент DOM...)

Ответ 5

Имела ту же проблему, что и вы... с высокими диаграммами. Я использовал Backbone.LayoutManager и в итоге взломал код, чтобы добавить обратный вызов postRender. Хотелось бы увидеть это как часть Backbone.js

Ответ 6

Если вы не хотите использовать setTimeout hack, я думаю, что этот способ более "нормальный":

Просто передайте элемент $el функции, которая должна управлять элементами, добавленными render(), а затем манипуляция DOM может быть выполнена на $el.

Ответ 7

Ну, об этом уже ответили, но для будущей ссылки у меня была эта проблема несколько раз. Я решил это, добавив пользовательские события, в этом случае это может быть что-то вроде

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. В зависимости от того, как ваш код структурирован, он может поместиться лучше или хуже. Опять же, я просто размещаю это как будущую ссылку и альтернативу.

Дополнительная информация: http://backbonejs.org/#Events

Ответ 8

Это должно быть сделано следующим образом:

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

образец с марионеткой, но идея также работает и для прожектов