如何在递归销毁dijit注册表后恢复它?

时间:2012-05-17 21:05:11

标签: dojo

我正在处理一个应用程序,并且正在做这样的事情:

dojo.ready(
           function(){ require['dojo/parser','dijit/registry','dojo/on'],function(.....){
           //find a dijit and wrap it in event handling code.});

我收到一条错误消息,表明dojo正在尝试注册一个已经在使用的ID的小部件。为了解决这个问题,我输入了这行代码:

           //before finding the dijit destroy the existing registry.

但是,逻辑上这会阻止下一行工作,因为现在没有可以连接事件的小部件。我怎样才能恢复dijit id?

2 个答案:

答案 0 :(得分:1)

最佳解决方案是找出您的代码尝试使用已在使用的ID注册窗口小部件的原因,并将其更改为不执行此操作。

@ mschr的解决方案应该可行,但我建议再次使用它,因为它可能会在许多其他地方破坏您的代码,并且您可能花费数小时调查应用程序的奇怪行为。

无论如何,如果您愿意这样做并自动销毁具有相同ID的小部件,请不要覆盖registry.add()方法。你可以这样做,但这并不意味着你应该这样做(特别是在编程中)。在dojo/aspect被调用之前,使用registry.add()来调用将使用相同ID销毁小部件的函数:

require([
    "dojo/aspect",
    "dijit/registry"
], function(
    aspect,
    registry
) {

    aspect.before(registry, "add", function(widget) {           
        if(registry.byId(widget.id)) {
            registry.byId(widget.id).destroy();
            // this warning can save you hours of debugging:
            console.warn("Widget with id==" + widget.id + " was destroyed to register a widget with the same id.");                    
        }
        return [widget];
    });

});

我很好奇如何在没有覆盖的情况下完成@mschr解决方案,所以我创建了一个jsFiddle进行实验:http://jsfiddle.net/phusick/feXVT/

答案 1 :(得分:0)

注册dijit后会发生以下情况;它由dijit.registry._hash引用:

function (widget) {
  if (hash[widget.id]) {
    throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered"); 
  }
  hash[widget.id] = widget;
  this.length++;
}

现在,你偶尔会有一个内容窗格,你可以在其中以编程方式放置窗口小部件(以编程方式,因此dojo.parser处理cpane.unload和derefences /销毁解析器实例化的窗口小部件)。

当发生这种情况时,您需要挂钩某种形式的“卸载”,例如,当您调用cpane.set('content'foo)或cpane.set('href',bar)时。需要使用Hook来销毁和取消注册您保存小部件的实例 - 否则您的程序中会出现内存泄漏。

通常情况下,一旦一个对象在任何地方都没有引用 - 它将被清除内存,但是对于复杂的对象,例如小部件可能是,'类变量'经常引用一些_outside _widget范围,它将小部件标记为不安全删除到垃圾收集器......一旦你明白这一点,你就会知道要执行适当的生命周期,而不是在完全理解这个概念之前。

可以做的是用自己的处理程序覆盖dijit.registry,并自动销毁任何双重部件的小部件,如下所示:

// pull in registry in-sync and with global scoped
// accees (aka dijit.registry instead of dj_reg)

require({

     async:false,
     publishRequireResult:true

  }, [

     "dijit.registry"

  ], function(dj_reg) {

   dijit.registry.add = function(widget) {

      // lets change this bit
      if (this._hash[widget.id]) {
          this._hash[widget.id].destroy(); // optinally destroyRecursively
          this.remove(widget.id)
      }
      this._hash[widget.id] = widget;
      this.length++;

   }
});
相关问题