子视图中的Backboe内存泄漏

时间:2015-10-15 17:11:56

标签: backbone.js memory-leaks

我的应用程序中仍然存在内存泄漏问题。我很乐意在不改变代码的情况下做到这一点。

var ItemsView = Backbone.View.extend({
    id:'products', // If I change it to el: document.getElementById('products') and without passing views into items object, my views are properly rendered but with memory leak
    events: { },
    initialize: function() {
      _.bindAll(this);
      this.listenTo(this.collection, 'reset',   this.reset);
      this.listenTo(this.collection, 'add',     this.addItem);
      this.listenTo(this.collection, 'change',  this.changeItem);
      this.listenTo(this.collection, 'destroy', this.delItem);
      this.items = [];
    },
    reset: function(){  console.log("reset");
      this.el.innerHTML = null;
      this.render();
    },
    render: function(){
      for(var i=0; i < this.collection.length; i++){
        this.renderItem(this.collection.models[i]);
      }
    },
    renderItem: function( model ){
      var itemView = new ItemView({ model: model });
      itemView.render();
      this.items.push(itemView);
      jBone(this.el).append(itemView.el);
    },
    addItem: function(){ console.log("addItem");
      this.renderItem();
    },
    changeItem: function(){ console.log("changeItem"); },
    delItem: function(){ console.log("delItem"); },
    remove: function() {
      _.invoke(this.items, 'remove');
      this.items = [];
      Backbone.View.prototype.remove.call(this);
    }
});
return ItemsView;

这是我的Itemsview,当用户点击orderview时执行它,为集合中的每个模型创建了ItemView:

var ItemView = Backbone.View.extend({
    tagName: "li",
    className: "productcc",
    initialize: function () {
        _.bindAll(this, 'addItem', 'removeItem', 'updateItem');
        this.listenTo(this.model, 'remove', this.removeItem);
        this.listenTo(this.model, 'change', this.updateItem);
    },
    events: {},
    render: function () {
      var model = this.model.toJSON();
      this.el.innerHTML += '<div class="tabody"><h4 class="tablename">'+model.title+'<h4>'+model.status+'</div>';
      return this;
    },
    addItem: function(){
      this.collection.create({"table_no":"demo"});
    },
    changeItem: function(e){
      e.preventDefault();
      this.model.save({ table_no: 'demo' });
    },
    updateItem: function(newstuff){
      console.log("updateItem");
      console.log(this.el);
    },
    delItem: function(){
      this.model.destroy({ silent: true });
    },
    removeItem: function(model){
      console.log("removeItem");
      console.log(model);
      var self = this;
      self.el.remove();
    }
});
return ItemView;

MY ROUTER:

var AppRouter = Backbone.Router.extend({

    routes: {
               ''        : 'home',
           'home'        : 'home',
        'customer/:customer_id': 'showItems'
    }
});

var initialize = function(options) {

  window.app_router = new AppRouter;
  window.socket     = io.connect('www.example.com');
  this.socketOrdersCollection = new SocketOrdersCollection();
  this.ordersView             = new OrdersView({ collection: this.socketOrdersCollection });
  this.socketOrdersCollection.fetch({ reset: true });

  app_router.on('route:home', function() { });
  app_router.on('route:showItems', function(customer_id) {
    if (this.itemsView) {
      this.itemsView.remove();
    }
    this.socketItemsCollection = new SocketItemsCollection();
    this.socketItemsCollection.fetch({ data: { id: customer_id}, reset: true  });

    this.itemsView = new ItemsView({
      collection: this.socketItemsCollection,
      model: { tableName: customer_id }
    });

  });
  Backbone.history.start();
};

点击其他订单后我还要删除ItemsView ... 感谢您的任何意见。

1 个答案:

答案 0 :(得分:1)

确定。让我来看看你在这里尝试的东西。

var ItemsView = Backbone.View.extend({
    el: document.getElementById('products'),
    events: { },
    initialize: function() {
      // everything you had before
      this.items = [];
    },
    // etc.
    renderItem: function( model ){
      var itemView = new ItemView({ model: model });
      itemView.render();
      this.items.push(itemView);
      jBone(this.el).append(itemView.el);
    },
    // etc.
    // we're overloading the view's remove method, so we clean up our subviews
    remove: function() {
      _.invoke(this.items, 'remove');
      this.items = [];
      Backbone.View.prototype.remove.call(this);
    }
});
return ItemsView;

然后在路由器中:

var initialize = function(options) {
  // etc.

  app_router.on('route:home', function() { });
  app_router.on('route:showItems', function(customer_id) {
    if (this.itemsView) {
      this.itemsView.remove();
    }

    // everything else the same

  });
  Backbone.history.start();
};

现在,您的ItemsView将清理其拥有的所有子项,当您更换客户时,您将清理已打开的任何ItemsView,然后再生成新的。{/ p >

修改 我现在看到你遇到了什么问题。

在您的路线处理程序中,您需要按照以下方式执行某些操作:

app_router.on('route:showItems', function(customer_id) {
  // everything you already have

  jBone(document.getElementById('container')).append(this.itemsView);

});