3

我遇到了 DOM 元素在被删除后留在内存中的问题。我已经设置了一个如下所示的示例。注意我正在使用主干布局管理器插件来管理我的视图(以及 jQuery)。

在删除列表中的一项之前和之后,我在 Chrome 中做了一个堆快照,并比较了两者:

Chrome 堆快照对比

如您所见,LI 元素仍在内存中。

删除视图时,主干布局管理器会调用 view.unbind() 和 view.stopListening()。

下面是示例代码。

ListOfViewsToDelete.js

var TestModel = Backbone.Model.extend({
  });

  var TestCollection = Backbone.Collection.extend({
    model: TestModel,
  });

  var ViewToDelete = Backbone.View.extend({
    template: "ViewToDelete",
    tagName: "li",
    events: {
      "click .delete-button": "deleteItem"
    },
    deleteItem: function() {
      this.$el.trigger('remove-item', [this.model.id]);
    }
  });

  var ListOfViewsToDelete = Backbone.View.extend({
    template: "ListOfViewsToDelete",
    initialize: function() {
      this.collection = new TestCollection();

      for (var i = 0; i < 5; i++) {
        this.collection.add(new TestModel({id: i}));
      }

      this.listenTo(this.collection, 'all', this.render);
    },
    events: {
      "remove-item": "removeItemFromCollection"
    },
    beforeRender: function() {

      this.collection.each(function(testModel) {
        this.insertView("ul", new ViewToDelete({
          model: testModel
        }));
      }, this);

    },
    removeItemFromCollection: function(event, model) {
      this.collection.remove(model);
    }
  });

路由器.js

app.useLayout("MainLayout").setViews({
                    "#main": new ListOfViewsToDelete()
                }).render();

ListOfViewsToDelete.html

<ul>
</ul>

ViewToDelete.html

View to delete
<button class="delete-button">x</button>
4

1 回答 1

4

您的代码有几个问题:

  • this.$el用作模型来触发remove-item事件。您应该改用您的模型。

  • 视图应该等待来自模型的事件以知道何时移除自己。

这是我想出的代码。如果它不起作用,请将您的代码发布到某个地方,以便我自己运行它。

var ViewToDelete = Backbone.View.extend({
    模板:“ViewToDelete”,

    标记名称:“李”,

    事件:{
      “点击 .delete-button”:“deleteItem”
    },

    初始化:函数(){
      this.listenTo(this.model, 'remove', this.remove);
    },

    删除项目:函数(){
      this.model.remove();
    }
});

默认实现view.remove()删除this.$el并停止监听模型:

删除:函数(){
  this.$el.remove();
  this.stopListening();
  返回这个;
},

编辑:感谢您在线发布您的代码。这就是我认为正在发生的事情(我也在为未来的观众记录)。

如果您拍摄快照,在 Detached DOM Tree 上进行过滤,您会看到:

Web 检查器快照

重要的部分是保留树:防止 LI 被删除的引用。唯一重要的是sizzle-1364380997635。它不是来自你的代码,它实际上来自 jQuery,更具体地说来自它的 Sizzle 引擎。关键来自这里:

https://github.com/jquery/sizzle/blob/master/sizzle.js#L33

如果您进一步查看代码,您会看到有一个缓存:

https://github.com/jquery/sizzle/blob/master/sizzle.js#L1802

所以,简而言之,你的代码不会泄漏,但是 jQuery 有一个内部缓存,可以防止它被删除。这个缓存只能包含几十个元素,所以它不会永远保留元素。

于 2013-03-26T17:52:58.537 回答