2012-04-27 52 views
5

我最近創建了我認爲是基於頁面的應用程序,它現在被嵌入式用作控件。 '控制'需要多次卸載/重新加載。這對訂閱和未被銷燬的dijit控件造成了問題。我已經制定了必要的斷開連接,registry.destroy邏輯,但它很乏味。是否有任何最佳做法,使控制集合可銷燬?Dojo垃圾收集/資源釋放技術?

這裏是展示什麼可以與基本的邏輯來完成的示例代碼: http://pastebin.com/bUUBUMP9

我問,如果一個框架存在類似於一個AppDomain凡在這方面創造任何東西都可以被清理。類似於將控件嵌入到IFRAME中,但不是。

回答

4

我可以看到兩個做法,將讓您的生活更輕鬆:

  1. Dijit的小部件延長dijit/_WidgetBase,因此一個小部件提供(dis)connect(un)subscribe方法。你應該使用它們來代替通用的aspect.connect()topic.subscribe()當接線小部件時,因爲這樣小部件斷開退訂自動銷燬時,所以你不必。

  2. 通過dijit/layout組織您的小部件,例如,使用dijit/layout/ContentPane而不是將小部件放置到DOM中,因爲這樣您需要撥打上的destroyRecursive(),它會正確銷燬它的所有子項。根據需要嵌套容器,以實現適當的粒度和視覺吸引力(這與Java的JPanel的概念相同)。

應用上述原則,您可能只需在層次結構中最高的容器上調用destroyRecursive()即可銷燬dijits。

0

phusick提供的答案比較好,但在這種情況下並不是真正的選擇。我想出了這樣一個解決方案:在不改變很多代碼

var dcHandles = [], dsHandles = [], dc = dojo.connect, ds = dojo.subscribe; 

dojo.connect = function() { 
    var h = dc.apply (dojo, arguments); 
    dcHandles.push (h); 
    return h; 
}; 

dojo.subscribe = function() { 
    var h = ds.apply (dojo, arguments); 
    dsHandles.push (h); 
    return h; 
}; 

dojo.subscribe ("unload", function() {  
    // restore dojo methods 
    dojo.connect = dc; 
    dojo.subscribe = ds; 

    var w, mll; 

    mll = dojo._windowUnloaders; 
    while (mll.length) { 
     (mll.pop())(); 
    } 

    if (dijit.registry) { 
     w = dijit.byId ("topLevelItem1"); 
     w && w.destroyRecursive(); 
     w = dijit.byId ("topLevelItem2"); 
     w && w.destroyRecursive(); 

     // destroy any other wijits 
     dijit.registry.forEach (function (w) { 
      try 
      { 
       w.destroyRecursive(); 
      } 
      catch (ex) 
      { 
       $.error (ex); 
      } 
     }); 
    } 

    dojo.forEach (dcHandles, function (h) { 
     dojo.disconnect (h); 
    }); 

    dojo.forEach (dsHandles, function (h) { 
     dojo.unsubscribe (h); 
    }); 

    // reset monad-like values 
    my.global.values.value1 = null; 

    dcHandles = []; 
    dsHandles = []; 


}); 

上面給了我一些保證,一切都被註銷/銷燬/解引用。