似乎无法清理分离的DOM元素

我正在使用jquery-ui Tabs ,我遇到了删除标签时出现的问题。 该选项卡似乎与其内容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 }); 

如您所见,视图都引用相同的集合; 集合中的每个模型都可以说代表一个标签(恰好是模型包含满足jquery-ui标签的必要信息)。 这些景观通过Marionette在一个地区展出。布局……相当标准。 通过单击选项卡容器中的链接来添加选项卡; 所有这一切都是为集合添加另一个模型,然后在主容器上调用选项卡(“刷新”),这样就会显示新选项卡。 通过单击选项卡右上角的“X”图标可以删除选项卡。

我花了很多时间试图追踪这个泄漏,我无法弄清楚我的代码中是否存在问题(我正在关闭视图/模型等等的方式?)或者是否存在问题jquery-ui tabs插件。

思考? 提前致谢!

更新#1根据要求,这里有一个jsfiddle演示问题 – 只需关闭选项卡,您将看到分离的元素被遗忘。

另外,截图:

在此处输入图像描述

更新#2这似乎是jquery-ui tabs小部件中的泄漏。 在jquery-ui网站上的小部件演示中会出现相同的行为。 我添加了几个标签,然后关闭它们,果然,它们仍然存在:

在此处输入图像描述

我用最新的(在撰写本文时)版本的jQuery UI(1.10.3)和之前的版本(1.10.2)测试了这个。

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

在你的jsFiddle中使用this.$el.empty()似乎可以解决分离的NodeList。

一些记录内存分析:

  • 观看http://www.youtube.com/watch?v=L3ugr9BJqIs
  • 使用3快照方法,2是不够的。 那是什么意思?
    • 开始新鲜,隐身模式并刷新
    • 拍摄快照(每次拍摄快照时都会发生强制GC)
    • 做点什么,拍快照(gc)
    • 做类似的事情,拍快照(gc)
    • 将快照2与快照1进行比较,使用+查找增量
    • 选择快照3的快照1和2之间分配的 摘要对象
    • 寻找你发现的比较2和1不应该存在的东西。 这些是韭菜

我发现了jQuery似乎韭菜的情况,因为它们在执行诸如调用.add()类的操作时会在.prevObject保存当前的jQuery对象。 也许对.contents()调用做了一些时髦的魔术。

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

  1. 放弃jQueryUI,转而使用Bootstrap
  2. 将closeTab函数(请参阅原始jsFiddle)更改为以下内容:

     closeTab: function (e) { e.stopPropagation(); e.preventDefault(); this.model.collection.remove(this.model); this.close(); } 

在该片段中,stopPropagation和preventDefault实际上是阻止此元素在DOM中保持分离(并在后续添加/删除时累积)的原因。 总结一下:这个问题是通过在触发事件对象后不调用stopPropagation / preventDefault创建的。 我已经更新了jsFiddle,以便正确删除制表符元素,为了后代,这里是结果的屏幕截图:

更新了jsFiddle

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