неудачный подход к удалению представлений зомби в backbonejs

так что у меня была такая же известная проблема с просмотрами зомби в моем магистральном приложении. Я пробовал это, чтобы стать супергероем :P

var Router=Backbone.Router.extend({
             routes:{
                  "":"loadDashboard",
                  "home":"loadDashboard",
                  'post-leads':"loadPostLeads"
                },
                initialize:function(){
                window.currentView=null;
                },

            loadPostLeads:function(){
            require(['views/post-leads'],function(leads){
            if(window.currentView!=null)
            {window.currentView.remove();}
            window.currentView=new leads();
            window.currentView.render();
            })

        },

              loadDashboard: function(){
        require(['views/dashboard'],function(dashboard){
            if(window.currentView!=null)
            {window.currentView.remove();}
            window.currentView=new dashboard();
            window.currentView.render();
            })
        }
          });

Это не работает. Я хотел что-то простое и не хочу использовать марионетку или что-то подобное ради этого. Что происходит не так выше? Это разумный подход?


person beNerd    schedule 14.03.2013    source источник
comment
Я LOLed @superhero :D   -  person Ahmad Alfy    schedule 14.03.2013
comment
:) что-нибудь об этом подходе?   -  person beNerd    schedule 14.03.2013


Ответы (1)


В принципе, то, что вы делаете, должно работать, но есть некоторые вещи, которые Backbone не может исправить, потому что он о них не знает.

Во-первых, вы должны убедиться, что используете последнюю версию Backbone (0.9.9 или новее). Были внесены некоторые улучшения в код привязки событий, что упрощает методу View.remove выполнение всей необходимой очистки.

Общие ошибки:

Прослушивание событий модели:

//don't use other.on (Backbone doesn't know how to clean up)
this.model.on('event', this.method);

//use this.listenTo (Backbone cleans up events when View.remove is called)
//requires Backbone 0.9.9
this.listenTo(this.model, 'event', this.method);

Прослушивание событий DOM за пределами вашего представления:

//if you listen to events for nodes that are outside View.el
$(document).on('event', this.method);

//you have to clean them up. A good way is to override the View.remove method
remove: function() {
  $(document).off('event', this.method);
  Backbone.View.prototype.remove.call(this);
}

Прямые ссылки:

//you may hold a direct reference to the view:
this.childView = otherView;

//or one of its methods
this.callback = otherView.render;

//or as a captured function scope variable:
this.on('event', function() {
  otherView.render();
});

Закрытия:

//if you create a closure over your view, or any method of your view, 
//someone else may still hold a reference to your view:
method: function(arg) {
  var self = this;
  return function() {
    self.something(x);
  }
}

Избегание следующих ловушек должно помочь вашим представлениям правильно очиститься.

Изменить на основе комментария:

Ах, вы не упомянули всю проблему в своем вопросе. Насколько я понимаю, проблема с вашим подходом заключается в том, что вы пытаетесь отобразить два представления в один и тот же элемент:

var View1 = Backbone.View.extend({el:"#container" });
var View2 = Backbone.View.extend({el:"#container" });

И когда вы удаляете View1, View2 отображается неправильно.

Вместо того, чтобы указывать представление el, вы должны отображать представления в элемент. На вашей странице вы должны иметь элемент #container и добавить элемент представления в контейнер.

loadPostLeads: function () {
  var self = this;
  require(['views/post-leads'], function (leads) {
    self.renderView(new leads());
  })
},

loadDashboard: function () {
  var self = this;
  require(['views/dashboard'], function (dashboard) {
    self.renderView(new dashboard());
  })
},

renderView: function(view) {
  if(window.currentView) {
    window.currentView.remove();
  }

  //the view itself does not specify el, so you need to append the view into the DOM
  view.render();
  $("#container").html(view.el);

  window.currentView = view;
}
person jevakallio    schedule 14.03.2013
comment
видите, когда я выполняю свой код, он удаляет его. но когда я создаю новое представление и делаю console.log(window.currentView), он показывает el как undefined :( - person beNerd; 14.03.2013
comment
@beNerd, отредактировал мой ответ. Вы действительно должны попытаться дать всю эту информацию в своем первоначальном вопросе. - person jevakallio; 14.03.2013
comment
Возможно, вы захотите, чтобы return Backbone.View.prototype.remove.call(this); в вашем remove соответствовало поведению по умолчанию. - person mu is too short; 14.03.2013