Javascript Can';似乎无法清理分离的DOM元素

Javascript Can';似乎无法清理分离的DOM元素,javascript,jquery,jquery-ui,backbone.js,marionette,Javascript,Jquery,Jquery Ui,Backbone.js,Marionette,我正在使用一个标签,当一个标签被移除时,我遇到了一个问题。该选项卡似乎与其内容div一起被删除,但当您查看Chrome DevTools概要文件中的堆时(在删除选项卡之后),您将看到选项卡li和div元素仍然存在,但已分离。随着时间的推移,重复添加/删除选项卡会导致这些元素累积。例如,如果添加选项卡10次,堆快照中将显示10个分离的div元素和10个分离的li元素: 我有以下意见: TabLabel = Marionette.ItemView.extend({ template: "#

我正在使用一个标签,当一个标签被移除时,我遇到了一个问题。该选项卡似乎与其内容div一起被删除,但当您查看Chrome DevTools概要文件中的堆时(在删除选项卡之后),您将看到选项卡li和div元素仍然存在,但已分离。随着时间的推移,重复添加/删除选项卡会导致这些元素累积。例如,如果添加选项卡10次,堆快照中将显示10个分离的div元素和10个分离的li元素:

我有以下意见:

TabLabel = Marionette.ItemView.extend({
    template: "#tab-label",
    tagName: "li",
    events: {
        "click .ui-icon-close": "closeTab"
    },  
    closeTab: function(e) {
        this.$el.contents().remove();
        this.model.collection.remove(this.model);
        $("#main-container").tabs("refresh");
        this.close();
    }   
}); 

TabContainer = Marionette.ItemView.extend({
    template: "#tab-container",
    tagName: "div",
    onBeforeRender: function() {
        this.$el.attr("id", "div-" + this.id);
    },  
    onClose: function() {
        // This removes the region that contains the container
        App.layout.removeRegion(this.containerRegion);
    }   
});

TabLabels = Marionette.CollectionView.extend({
    tagName: "ul"
});

TabContainers = Marionette.CollectionView.extend({
    tagName: "div"
});
视图的实例化如下所示:

tabs = new TabsCollection(); // Create a new collection instance

var tabLabelView = new TabLabels({
    itemView: TabLabel,
    collection: tabs
}); 

var tabContainerView = new TabContainers({
    itemView: TabContainer,
    collection: tabs
}); 
如您所见,两个视图都引用同一个集合;集合中的每个模型都可以说代表一个选项卡(恰好模型包含满足jQueryUI选项卡的必要信息)。视图通过木偶显示在区域中。布局。。。相当标准。通过单击选项卡容器中的链接来添加选项卡;所有这一切只是将另一个模型添加到集合中,然后调用主容器上的选项卡(“刷新”),从而显示新选项卡。通过单击选项卡右上角的“X”图标可以删除选项卡

我花了很多时间试图追踪这个漏洞,但我不知道这是我的代码中的问题(可能是关闭视图/模型等的方式?),还是jquery ui选项卡插件中的问题

想法?提前谢谢

根据要求更新#1下面是一个演示问题的示例--只需关闭选项卡,您就会看到分离的元素被遗留下来

还有一个屏幕截图:

更新#2这似乎是jquery ui选项卡小部件中的漏洞。在jQueryUI网站上的中也会发生相同的行为。我添加了几个选项卡,然后将它们关闭,果然,它们仍然存在:


我已经用jQuery UI(1.10.3)的最新版本(撰写本文时)和以前的版本(1.10.2)对此进行了测试。

是否有理由使用
this.$el.contents().remove()
而不是
this.$el.empty()

在您的JSFIDLE中使用
this.$el.empty()
似乎可以修复分离的节点列表

内存分析的几个注意事项:

  • 监视
  • 使用3个快照的方法,2个是不够的。这是什么意思?
    • 重新启动、隐姓埋名模式和刷新
    • 拍摄快照(每次拍摄快照时都会发生强制GC)
    • 做点什么,拍快照(gc)
    • 执行类似操作,拍摄快照(gc)
    • 比较快照2和快照1,查找具有+
    • 为快照3选择摘要和在快照1和快照2之间分配的对象
    • 寻找你在比较2和1时发现的不应该存在的东西。这些是韭菜

我发现jQuery似乎有问题,因为在执行诸如调用
.add()
之类的操作时,它们将当前jQuery对象保存在
.prevObject
中。也许对
.contents()
的调用会产生一些奇怪的效果。

所以我最终通过做两件事解决了这个问题(很久以前):

  • 抛弃jQueryUI,支持Bootstrap
  • 将closeTab函数(参见原始JSFIDLE)更改为以下内容:

    closeTab: function (e) {
        e.stopPropagation();
        e.preventDefault();
        this.model.collection.remove(this.model);
        this.close();
    }
    
  • 在该片段中,stopPropagation和preventDefault实际上阻止了该元素在DOM中保持分离(并在后续添加/删除时累积)。总而言之:这个问题是在事件对象被触发后没有调用stopPropagation/preventDefault造成的。我已经更新了,以便它正确地删除选项卡元素,对于后代,下面是结果的屏幕截图:


    如您所见,单击“X”关闭选项卡元素后,没有任何选项卡元素保持分离状态。唯一分离的元素是来自JSIDdle接口的元素。

    您能发布一个JSIDdle来演示这一点吗?我想知道问题是否在于没有得到支持的事件处理程序removed@JaniHartikainen我认为这可能是问题所在,但我尝试调用unbind()的多个排列在close函数中,结果是相同的。您是否尝试在快照之间强制垃圾收集器以确保您没有实际计算未引用的项目?@prodigitalson是的,它留下了分离的文本节点。根据,这种行为是经过设计的:还要注意,与大多数jQuery方法一样,.children()不返回文本节点;要获取包括文本和注释节点在内的所有子节点,请使用.contents()。我已经使用.empty()而不是.contents().remove()对此进行了测试,结果是一样的。