Вызов javascript при просмотре представлений в BackBone js. обратный вызов после рендера?
Вот, вызов рендеринга позвоночника:
render: function() {
$(this.el).html(this.template({title: 'test'})); //#1
this.renderScatterChart();
return this;
},
поэтому я называю стандартный рендер в # 1. и затем я вызываю метод [на этот раз, это оболочка для построения диаграммы lib], которая ищет div. div обрабатывается вызовом рендеринга. но на данный момент он еще не привязан к DOM (правильно?). так что графический вызов печально умирает.
Каков шаблон для этого? Мне бы очень хотелось услышать, что есть обратный вызов post-render. Я пробовал несколько хаков вокруг этого, и иногда я получаю диаграмму, чтобы работать, но события не связываются.
Ответы
Ответ 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 ...
}
образец с марионеткой, но идея также работает и для прожектов