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

Backbone.js - удалить все подпункты

У меня есть верхний уровень PageView, который будет повторно отображаться при каждом изменении маршрута. У меня много вложенных подзадач, встроенных в этот PageView. Если бы мне пришлось повторно визуализировать PageView, мне нужно удалить/развязать все вложенные под-представления вместе с PageView или мне нужно только удалить/развязать PageView? Если мне нужно удалить/развязать все под-представления, как лучше всего это сделать?

4b9b3361

Ответ 1

Да, вам нужно правильно удалить и развязать их:

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

Легкий способ сделать это - сохранить массив ваших под-представлений в родительском представлении. Затем в методе 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);

}