尝试注册具有id的小部件,但该ID已经注册

时间:2014-09-11 21:26:54

标签: javascript dojo

我有两个按钮,并希望根据按下的按钮将不同的自定义模板窗口小部件加载到div中。它在第一次单击时工作正常,但在再次单击任一按钮时会出现主题错误。我已经有了这个非常简单的例子来尝试让概念运作

我的模板代码(有两个非常相似):

define([
  "dojo/_base/declare",
  "dijit/_WidgetBase",
  "dijit/_TemplatedMixin",
  "dojo/text!Templates/Person.htm"
], function (declare, _WidgetBase, _TemplatedMixin, personTpl) {
    return declare([_WidgetBase, _TemplatedMixin], {
        templateString: personTpl
    });
});

我的模板(有两个非常相似):

<div>
  <p>Bob Jones</p>
</div>

主页:

 <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>

感谢您的任何想法

2 个答案:

答案 0 :(得分:3)

嘿,我拿了你的代码,我创建了一个jsfiddle测试,现在我意识到你的问题是什么。

如果我理解正确你在创建第二个对象和其他对象时遇到麻烦。对于第一个小部件,我相信你没事。

所以,第一个对象没问题的原因是因为dojo使用你的id创建了widget,并且它们有一个名为widgetid的东西。 widgetid放在一个列表中,如果你调用widget的destroy方法,它就会从那里删除;但是,当您调用窗口小部件的destroy方法时,它将破坏该节点。这是解决问题的jsfiddle链接,如果我理解正确,请告诉我。

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();
     });

我不喜欢在div中使用id来创建我的小部件,而不是我通常使用对小部件的引用,但这取决于你。请记住销毁窗口小部件并重新创建节点。我很确定有一种方法可以破坏小部件,保持节点活着,但我没有时间找到它。遗憾。

答案 1 :(得分:3)

两个按钮都尝试使用相同的ID("page")创建窗口小部件,并且没有任何内容会破坏此窗口小部件。 Dijit维护一个由其ID标识的小部件注册表,并且ID自然应该是唯一的,因此任何创建具有已注册小部件ID的小部件的尝试都将失败并显示该错误。

要首先正确销毁窗口小部件,要么维护对它的引用(在任何单个单击回调范围之外的变量中),要么使用dijit/registry.byId再次获取对窗口小部件的引用。然后调用其destroyRecursive方法。无论哪种方式,您都不需要依赖全局变量。

示例:http://jsfiddle.net/zdbvs5c9/

PS:我还应该提到,将new Widget(...).startup()分配给变量是没有意义的,因为startup不会返回任何内容。 placeAt可以链接,startup不是(因为它始终不适合立即调用startup,因为它只需要在小部件之后调用在文件流程中。)