0

I have a quiz application built in backboneJS, I have three views. A QuizView which shows the overall progress and back/next buttons. A PageView that contains a group of questions and a QuestionView for each question.

When a user goes to the next page in a quiz I remove the current PageView by calling a destroy function that calls Backbone's remove() on the page itself and all the questions. (all listeners are attached with listenTo)

It's my expectation that after I do this that DOM nodes should not longer be reflected in memory timeline. I've attached a view of the DOM node count from Chrome dev tools and you can see it goes up as you go to new pages.

I also took a heap snapshot and when I look at the detached DOM items they all have one item (the div container for a page) that has a single item in the retaining tree. I'm assuming this is why they are not being collected.

Can anyone provide insight at to why the DOM node count continuously goes up?

Also this is my destroy function in PageView:

destroy: function(){
    console.log("PageView :: destroy " + this)
    _.each(this.childViews, function(view){
        view.remove();
    });

    this.remove();
}

Timeline View Heap Snapshot

4

2 回答 2

0

我知道这是一篇旧帖子,但我遇到了同样的问题。在 chrome 开发工具中记录时,垃圾收集器被阻止运行。您必须通过单击 GC 按钮手动运行它。

开发工具 GC 按钮

我构建了这个小提琴来创建节点,然后在创建 10 个时将它们全部删除。认为从 dom 中删除节点数时应该重置它们。它没。然后我注意到顶部的GC按钮...

猜猜你现在可以将演示注入 SO。不需要小提琴。这很酷...

var test = document.getElementById("test");
var stuff = document.getElementById("stuff");

test.addEventListener("click", testFn);

var count = 0;

function testFn(){
    
    console.log('create '+count);
    
    // create a new div element 
    // and give it some content 
    var newDiv = document.createElement("div"); 
    var newContent = document.createTextNode("test "+count); 
    count++;
    
    newDiv.appendChild(newContent); //add the text node to the newly created div. 
    
    stuff.appendChild(newDiv);
    
    if(count == 10){
        
        while (stuff.firstChild) {
            stuff.removeChild(stuff.firstChild);
        }			
        
        count = 0;
        
    }	
    
};
<div id="test">page should start with 14 nodes. click me.</div>
<div id="stuff">&nbsp;</div>

于 2015-02-21T13:28:28.347 回答
0

只要您的对象之间有任何引用,它们就没有资格进行垃圾收集。这些视图是“僵尸视图”。这篇文章完美地解释了如何处理这种情况:

僵尸!跑!(管理主干应用程序中的页面转换)


经过

view.remove() 从 DOM 中删除一个视图,并调用 stopListening 来删除该视图已监听的任何绑定事件。

您基本上删除了events: {}该视图的 和 DOM。然而,监听trigger事件和模型事件如

this.model.on('reset', this.render, this)

仍然活着并持有对您的视图的引用,使其没有资格进行垃圾收集。

于 2013-05-10T07:05:14.340 回答