16

我正在使用jquery-ui 选项卡,并且在删除选项卡时出现问题。该选项卡及其内容 div 似乎已被删除,但是当您查看 Chrome DevTools Profiles 中的堆时(在删除选项卡之后)您会看到选项卡 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.Layout 显示在一个区域中......非常标准。添加选项卡是通过单击选项卡容器中的链接来完成的;所做的只是将另一个模型添加到集合中,然后在主容器上调用 tabs("refresh"),这会使新选项卡出现。通过单击选项卡右上角的“X”图标来删除选项卡。

我花了很多时间试图追踪这个泄漏,但我不知道这是否是我的代码中的问题(也许是我关闭视图/模型/等的方式?)或者它是否是一个问题jquery-ui 选项卡插件。

想法?提前致谢!

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

另外,截图:

在此处输入图像描述

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

在此处输入图像描述

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

4

2 回答 2

4

this.$el.contents().remove()您使用而不是有原因this.$el.empty()吗?

this.$el.empty()在你的那个 jsFiddle 中使用似乎可以补救分离的 NodeList。

一些笔记内存分析:

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

我发现了 jQuery 似乎是韭菜的情况,因为它们在.prevObject执行某些操作(如调用.add(). 也许那个电话是为了.contents()做一些时髦的魔术。

于 2013-09-03T12:53:22.107 回答
3

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

  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 界面的元素。

于 2013-12-19T15:24:32.473 回答