我最近创建了我认为是基于页面的应用程序,它现在被嵌入作为控件使用。 “控制”需要多次卸载/重新加载。这会导致订阅和未被销毁的dijit控件出现问题。我已经找到了必要的断开连接,注册表.detroy逻辑,但它很乏味。是否有任何最佳实践可以使控件集合具有可销毁性?
以下示例代码显示了基本逻辑可以完成的任务: http://pastebin.com/bUUBUMP9
我在问一个框架是否存在类似于AppDomain的框架,在该框架中可以清除在该上下文中创建的任何内容。类似于在IFRAME中嵌入控件......但不是。
答案 0 :(得分:4)
我可以看到两种让您的生活更轻松的做法:
Dijit小部件扩展dijit/_WidgetBase
,因此小部件提供(dis)connect
和(un)subscribe
方法。在连接小部件时,您应该使用它们而不是通用aspect.connect()
和topic.subscribe()
,因为这样小部件会在销毁时自动断开和取消订阅,所以你不必。
通过dijit/layout
整理您的小部件,例如使用dijit/layout/ContentPane
而不是将小部件放入DOM中,因为这样您只需要在destroyRecursive()
上调用ContentPane
,它就会正确地销毁它的所有子节点。根据您的需要嵌套容器,以获得适当的粒度和视觉吸引力(这与Java JPanel
的概念相同)。
应用上述原则,您可能只需要在层次结构中最高的容器上调用destroyRecursive()
来销毁dijits。
答案 1 :(得分: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 = [];
} );
上面给了我一些保证,即在不改变大量代码的情况下,所有内容都会被取消注册/销毁/取消引用。