0

我正在开发一个应用程序并且正在做这样的事情:

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?

4

2 回答 2

1

最好的解决方案是找出为什么您的代码试图注册一个具有已在使用的 id 的小部件,并将其更改为不这样做。

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

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

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/

于 2012-05-18T13:54:29.610 回答
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 并取消引用/销毁解析器实例化的小部件)。

发生这种情况时,您需要挂钩某种形式的“卸载”,例如,当您调用 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++;

   }
});
于 2012-05-18T09:30:18.840 回答