javascript 试图用 id 注册小部件,但该 id 已经注册
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25797195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Tried to register widget with id but that id is already registered
提问by pvitt
I have two buttons and would like to load a different custom template widget into a div depending on which button is pressed. It works fine the first click, but then comes up with the subject error when either of the buttons is clicked again. I've got this very simplified example to try and get the concept working
我有两个按钮,想根据按下的按钮将不同的自定义模板小部件加载到 div 中。第一次点击它工作正常,但是当再次点击任何一个按钮时出现主题错误。我有这个非常简单的例子来尝试让这个概念发挥作用
my template code (there are two very similar to this):
我的模板代码(有两个与此非常相似):
define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/text!Templates/Person.htm"
], function (declare, _WidgetBase, _TemplatedMixin, personTpl) {
return declare([_WidgetBase, _TemplatedMixin], {
templateString: personTpl
});
});
my template (there are two very similar to this):
我的模板(有两个与此非常相似):
<div>
<p>Bob Jones</p>
</div>
Main page:
主页:
<body class="claro">
<script>
require([
"dijit/form/Button",
"Templates/Person", "Templates/Person2", "dojo/domReady!"
], function (Button, Person, Person2) {
var Button1 = new Button({
label: "Person1",
onClick: function () {
var p = new Person({}, "page");//error occurs here after a button has been pressed once
}
}, "btnPerson1").startup();
var Button2 = new Button({
label: "Person2",
onClick: function () {
var p2 = new Person2({}, "page"); //error occurs here after a button has been pressed once
}
}, "btnPerson2").startup();
});
</script>
<button id="btnPerson1" type="button"></button>
<button id="btnPerson2" type="button"></button>
<div id="page"></div>
</body>
Thanks for any ideas
感谢您的任何想法
采纳答案by Vicente Teodoro
Hey I took your code and I created a jsfiddle test and now I realized what is your problem.
嘿,我拿了你的代码,我创建了一个 jsfiddle 测试,现在我意识到你的问题是什么。
If I understood correctly you are getting in trouble just when creating the second object and the other ones. For the first widget I believe you are ok.
如果我理解正确的话,您会在创建第二个对象和其他对象时遇到麻烦。对于第一个小部件,我相信你没问题。
So, the reason that the first object is ok is because the dojo creates the widget using your id and they have something named widgetid. The widgetid is put in a list and it is just removed from there if you call the destroy method of the widget; however, when you call the destroy method of your widget it will destroy the node. Here is the jsfiddle link that fixes your problem, please let me know if I understood correctly.
所以,第一个对象没问题的原因是因为 dojo 使用您的 id 创建了小部件,并且它们有一个名为 widgetid 的东西。widgetid 放在一个列表中,如果您调用小部件的 destroy 方法,它就会从列表中删除;但是,当您调用小部件的 destroy 方法时,它会销毁节点。这是解决您的问题的 jsfiddle 链接,如果我理解正确,请告诉我。
http://jsfiddle.net/cyeddpe5/26/
http://jsfiddle.net/cyeddpe5/26/
define("Person",[
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
], function (declare, _WidgetBase, _TemplatedMixin, personTpl) {
return declare([_WidgetBase, _TemplatedMixin], {
templateString: "<div><p>Bob Jones</p></div>"
});
});
require([
"dijit/form/Button",
"Person", "dojo/domReady!"
], function (Button, Person) {
var Button1 = new Button({
label: "Person1",
onClick: function () {
//Here is the trick
if(window.p)
{
window.p.destroy(false);
var page = document.createElement("div");
dojo.body().appendChild(page);
page.setAttribute("id","page");
}
window.p = new Person({}, "page");//error occurs here after a button has been pressed once
}
}, "btnPerson1").startup();
});
I do not like to use id in a div to create my widgets, instead of this I normally use a reference to the widget, but it is up to you. Remember to destroy the widget and recreate the node. I am quite sure that there is a way to destroy the widget keeping the node alive, but I did not have time to find it. Sorry.
我不喜欢在 div 中使用 id 来创建我的小部件,而不是我通常使用对小部件的引用,但这取决于您。请记住销毁小部件并重新创建节点。我很确定有一种方法可以销毁保持节点活动的小部件,但我没有时间找到它。对不起。
回答by Ken Franqueiro
Both buttons attempt to create a widget using the same ID ("page"
), and nothing ever destroys this widget. Dijit maintains a registry of widgets keyed by their ID, and IDs are naturally expected to be unique, so any attempt to create a widget with an ID of an already-registered widget will fail with that error.
两个按钮都尝试使用相同的 ID ( "page"
)创建一个小部件,并且没有任何东西会破坏这个小部件。Dijit 维护着一个以 ID 为键的小部件注册表,而 ID 自然期望是唯一的,因此任何尝试使用已注册小部件的 ID 创建小部件的尝试都将因该错误而失败。
To properly destroy the widget first, either maintain a reference to it (in a variable outside the scope of any of your individual click callbacks) or use dijit/registry.byId
to get a reference to the widget again. Then call its destroyRecursive
method. Either way, you should not need to rely on global variables.
要首先正确销毁小部件,请维护对它的引用(在任何单个单击回调范围之外的变量中)或使用dijit/registry.byId
再次获取对小部件的引用。然后调用它的destroyRecursive
方法。无论哪种方式,您都不需要依赖全局变量。
Examples: http://jsfiddle.net/zdbvs5c9/
例子:http: //jsfiddle.net/zdbvs5c9/
PS: I should also mention that assigning new Widget(...).startup()
to a variable is meaningless, because startup
doesn't return anything. placeAt
is chainable like that, startup
isn't (since it isn't always appropriate to immediately call startup
anyway, since it needs to be called only after the widget is in document flow).
PS:我还应该提到分配new Widget(...).startup()
给变量是没有意义的,因为startup
不返回任何内容。 placeAt
是可链接的,startup
不是(因为它并不总是适合立即调用startup
,因为它只需要在小部件进入文档流后调用)。