У меня есть верхний уровень PageView, который будет повторно отображаться при каждом изменении маршрута. У меня много вложенных подзадач, встроенных в этот PageView. Если бы мне пришлось повторно визуализировать PageView, мне нужно удалить/развязать все вложенные под-представления вместе с PageView или мне нужно только удалить/развязать PageView? Если мне нужно удалить/развязать все под-представления, как лучше всего это сделать?
Backbone.js - удалить все подпункты
Ответ 1
Да, вам нужно правильно удалить и развязать их:
Легкий способ сделать это - сохранить массив ваших под-представлений в родительском представлении. Затем в методе close
на родительском представлении проведите цикл по массиву и вызовите метод close
для дочерних видов:
ParentView = Backbone.View.extend({
initialize: function(){
this.childViews = [];
},
render: {
for (var i = 0; i < 10; i++){
var childView = new ChildView();
// do stuff with the child view
this.childViews.push(childView);
}
},
close: function(){
this.remove();
this.unbind();
// handle other unbinding needs, here
_.each(this.childViews, function(childView){
if (childView.close){
childView.close();
}
})
}
});
Обязательно вызовите метод close
в родительском представлении, когда вы будете готовы к его удалению/замене. Это обеспечит правильную очистку всех детей (при условии, что все они имеют свой собственный метод close
).
Ответ 2
Простой и модульный класс, который может вам пригодиться.
ContainerView = Backbone.View.extend({
initialize: function() {
this.children = [];
},
remove: function() {
Backbone.View.prototype.remove.apply(this, arguments);
this.removeAllChildren();
},
removeAllChildren: function() {
_.each(this.children, function(view) { view.remove(); });
this.children = [];
},
appendAllChildren: function() {
_.each(this.children, function(view) { this.$el.append(view.render().$el); }, this);
}
});
использование:
MyView = ContainerView.extend({
render: function() {
this.removeAllChildren();
this.$el.empty();
// For each child view...
// this.children.push(new SomeControl(...));
this.appendAllChildren();
return this;
}
});
Ответ 3
Вместо того, чтобы хранить массив дочерних элементов, можно выполнить итерацию всех свойств вашего представления и посмотреть, какие из них являются экземпляром Backbone.View; вам нужно будет установить свойство для каждого дочернего представления в родительском представлении.
В приведенном ниже примере дочерние представления устанавливаются в свойства родительского представления. Я не уверен, что производительность будет зацикливаться на всех свойствах, однако это может быть проще, чем отслеживать отдельную структуру данных для дочерних просмотров.
Пример:
var ContextView = Backbone.View.extend({
initialize: function() {
// views render themselves via their initialize methods
this.titlebar = new TitlebarView({el: $("#titlebar")});
this.toolbar = new ToolbarView({el: $("#toolbar")});
this.content = new ContentView({el: $("#content")});
},
removeChildViews: function() {
for(var prop in this){
if (this[prop] instanceof Backbone.View) {
console.log("This is a view: "+ prop + ' in ' + this[prop]);
}
}
},
render: function() {
this.$el.html(this.el);
}
});
Ответ 4
Немного напоминает Zengineer, мне нравится патч Backbone.View.remove глобально, как показано ниже, так что любые дочерние представления, прикрепленные к нему, удаляются
var originalRemove = Backbone.View.prototype.remove;
Backbone.View.prototype.remove = function ()
{
for (var view in this){
if (this[view] instanceof Backbone.View && this[view] != this) {
this[view].remove();
}
}
originalRemove.apply(this, arguments);
}