【问题标题】:Removing backbone views but DOM node count keeps going up?删除主干视图但 DOM 节点数不断增加?
【发布时间】:2013-05-04 10:17:42
【问题描述】:

我有一个内置在主干JS 中的测验应用程序,我有三个视图。显示整体进度和后退/下一步按钮的 QuizView。包含一组问题和每个问题的 QuestionView 的 PageView。

当用户在测验中进入下一页时,我通过调用一个销毁函数来删除当前的 PageView,该函数在页面本身和所有问题上调用 Backbone 的 remove()。 (所有监听器都附有listenTo)

我的期望是,在我这样做之后,DOM 节点不应再反映在内存时间轴中。我附上了来自 Chrome 开发工具的 DOM 节点数视图,您可以看到它随着您进入新页面而增加。

我还拍摄了一个堆快照,当我查看分离的 DOM 项目时,它们都有一个项目(页面的 div 容器)在保留树中有一个项目。我假设这就是他们没有被收集的原因。

谁能提供关于为什么 DOM 节点数持续上升的见解?

这也是我在 PageView 中的销毁功能:

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

    this.remove();
}

【问题讨论】:

    标签: javascript backbone.js memory-management garbage-collection google-chrome-devtools


    【解决方案1】:

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

    我构建了this fiddle 来创建节点,然后在创建 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>

    【讨论】:

      【解决方案2】:

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

      Zombies! RUN! (Managing Page Transitions In Backbone Apps)


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

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

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

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

      【讨论】:

      • 这是有道理的,但是在我的情况下,我不会对任何事件使用“on”或“trigger”,所以我认为默认的删除功能应该足够了。
      • 如果你的视图/集合/模型中有任何listenTo,最好选择'this.model.off(null, null, this)'或'this.collection.off(null,空,这个)'
      猜你喜欢
      • 2012-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多