我正在处理一个应用程序,并且正在做这样的事情:
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?
答案 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++;
}
});