dojo: 小部件已注册错误

Posted

技术标签:

【中文标题】dojo: 小部件已注册错误【英文标题】:dojo: widget already registered error 【发布时间】:2015-05-14 15:24:52 【问题描述】:

我知道这似乎是一个常见错误,我已经尝试实现一些 jquery 或 Dojo 代码来解决问题,但到目前为止没有任何帮助 - 我不断收到相同的错误:小部件已注册 ID...

这是我的代码:

$( "div" ).remove( "#div_temperature_legend" ); //jquery        
dojo.create("div",  id: "div_temperature_legend", innerhtml: "<p></p>" , "legendPanel"); 
var legend = new esri.dijit.Legend(
              map: map,
              layerInfos: [ layer: layer, title: "Temperature" ],
    , "div_temperature_legend");
legend.startup();

上面的代码在一个按钮点击函数中,这个函数本身就是一个大的道场require()函数的一部分;并第一次工作。 jQuery 行似乎确实被删除了,因为图例不会在新创建的 div_temperature_legend 层中重复。

无论如何,我已经尝试过 dojo 的 destroy() 函数,但我仍然得到同样的错误。我想不知何故,我需要在某个地方 register 这个 div 然后销毁它。但是怎么做?在哪里?在我的代码上下文中?

理想情况下,代码应该检测小部件是否存在并且不会创建另一个图例。

谢谢。

【问题讨论】:

jquery 代码删除了div,但小部件的引用(即 esri.dijit.Legent 在注册表中仍然可用。要销毁小部件,这会删除注册表中的引用需要做这样的事情。legend.destroy() 在创建 new esri.dijit.Legend 之前。 【参考方案1】:

错误在于dojo 小部件的错误处理。一旦创建,它将通过其 ID 在注册表散列中设置。你也可以 a) 处理小部件 dojo 方式 或者 b) 每次为小部件创建唯一 ID。

如果您有多个相同类型的小部件,则使用 ID 不是一个好主意。最好跳过 ID 并使用 class 属性。 ID 将被自动分配,但您对此不感兴趣,因为选择器可以使用您分配的类名。

【讨论】:

好的,那么如何使用类属性呢?除非我以某种方式将其删除,否则小部件不会继续获取图例内容吗?就像我现在正在使用 jquery 一样?谢谢 $('.myWidgetType').forEach( function(el) dijit.byNode(el).destroy(); //1.销毁小部件的所有实例 $('.esriLegend').forEach( function(el) dijit.byNode(el).destroy(); // 2. 以与您相同的方式创建一个新实例,但使用 className 代替id.var node = dojo.create("div", class: "esriLegend", innerHTML: "

" , "legendPanel"); new esri.dijit.Legend(... ,node).startup(); 模板化的小部件使用起来稍微简单一些。
【参考方案2】:

这是我基于 @Sasha 的唯一 Div ID 理念实现我的解决方案的方式:

$("#"+div_legend_global).remove();
div_legend_global = "div_" + new Date().getTime().toString();//div_legend_global defined globally
dojo.create("div",  id: div_legend_global, innerHTML: "<p></p>"    , "legendPanel"); 
var legend = new esri.dijit.Legend(
              map: map,
              layerInfos: [ layer: layer, title: "Temperature" ],
         , div_legend_global);
legend.startup();

所以我定义了一个名为div_legend_global 的全局变量,然后在按钮单击函数中为其分配唯一值。然后,该唯一值将成为 create Legend() 函数的 ID。在后续调用之后,jquery 会移除唯一的 div,从而防止显示多个图例实例。

现在,Dojo 可能会将 div 保留在其堆栈中,我认为从堆栈中删除会更好。但我现在还好。

谢谢@Sasha。

【讨论】:

我认为这会在您的代码中造成内存泄漏。即使 domNode 被销毁,dojo 对象仍然驻留在内存中。另一种方法是使用dijit.registry( 'widget_id').destroy(),然后重新创建图例小部件。 好的,但是我在哪里以及如何将 div 添加到注册表中——我想我曾怀疑我需要做类似的事情,但无法弄清楚。我确实尝试过 domConsrtruct.destroy() 但没有帮助。谢谢 Meengla 如果您正在创建它,则无需注册小部件。它应该已经注册了。如果您绝对需要 ID,您可以考虑另一种选择,即每次使用注册表的 getUniqueId 函数为您提供一个唯一 ID,您可以将其存储在您选择的某个变量中。有关 getUniqueId 和所有其他注册表方法的更多信息,请参阅 dojotoolkit.org/api/#1_10dijit_registry_getUniqueId。 frank 的评论也应该是一个答案。 ;) 这是mixing up DOM and Dijit APIs 的经典案例(该博文已经过时,但其中的破坏部分在 5 年后仍然适用)。 DOM 销毁 API 对 Dijit 小部件一无所知。 对不起,但没有一个建议奏效:我试过 Frank 的但仍然得到同样的错误——显然破坏不起作用。我可以通过使用 'var node_legend = dom.byId("div_legend")' 进行检测,然后尝试使用 Frank 和 'domConstruct.destroy("div_legend");'但没有效果——同样的错误。我继续前进。这个留到以后再说。谢谢大家。

以上是关于dojo: 小部件已注册错误的主要内容,如果未能解决你的问题,请参考以下文章

dojo 小部件不会发出事件

DOJO 错误 ID 已注册

dijit.registry.filter / dijit.registry.map 不会迭代,尽管 dijit.registry 充满了已注册的小部件?

以编程方式(但不是以声明方式)实例化小部件时出现 Dojo 重复 ID 错误

dojo:通过 dom 节点销毁所有小部件

错误:尝试使用 id==grid1 注册小部件,但该 id 已注册