Dojo 1.9:当父窗口小部件启动时,placeAt 自动调用启动

Posted

技术标签:

【中文标题】Dojo 1.9:当父窗口小部件启动时,placeAt 自动调用启动【英文标题】:Dojo 1.9: placeAt automatically calls startup when parent widget has started up 【发布时间】:2013-09-27 15:40:26 【问题描述】:

Dojo v1.9

我正在编写一些代码,以编程方式创建一个小部件,我需要将其放入布局小部件中。我目前遇到的问题是startup被dojo自动主动调用。

如果布局小部件已经启动,则在使用placeAt(domNode) 时调用startup。这是不可取的,最好是显式调用startup

我这样说是因为在当前情况下,startup 被调用了两次,一次是在 placeAt 被调用时,一次是在 startup 被我直接手动调用时。

Dojo docs 和related tutorials 表示,在以编程方式创建小部件时,您应该始终手动调用startup 以确保发生正确的解析。但是startup 的自动调用导致了一些问题,在启动时会出现重复的操作,我可以将它们移到postCreate,但这只是隐藏了问题。

这是一个小部件创建/启动的简单示例...

var myWidget = new Widget();
myWidget.placeAt('mainContent');
myWidget.startup();

mainContent 是 ContentPane 中的一个 div,这里是布局 html...

<body class="claro">
    <div id="appLayout" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design: 'headline'">
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'">
            <div id="mainContent"></div>
        </div>
        <div class="edgePanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'top'">Some text here</div>
        <div id="leftCol" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'left'"></div>
    </div>
</body>

代码有效,这确实是我试图解决的 startup 被调用两次的问题。


更新:解决方法

建议在 startup 函数中针对小部件私有变量 _started 进行检查,这至少可以保护我免于重复,这是我的检查示例。

startup: function()
    if (typeof this._started === "undefined")
        // call inherited and pass on arguments
        this.inherited(arguments);

        // then do what ever you need here
    

请注意,我必须使用typeof 而不是boolean 检查,即使在startup 之后_started 的值是true。这是因为我发现直到 startup 至少运行一次后才真正声明变量,这需要注意。

无论如何,这为我提供了一种解决方法,但不能解决 startup 被 dojo 多次调用的问题。

【问题讨论】:

在答案中查看我的更新。您可以在启动代码之后将 _started 设置为 true。 @Sean Zhao 我相信_started 在第一次启动后无论如何都会设置为truefalse,只要this.inherited 被调用,或者startup 未被覆盖在您的自定义小部件中。 【参考方案1】:

startup() 在 Dojo 中经常被自动调用。例如,每当您在容器小部件上调用 addChild() 时,都会调用子组件的 startup() 方法。查看_WidgetBase 的来源,placeAt 也是其中之一。

当您使用dom-construct 之类的东西将dojo 小部件直接放置在DOM 节点上时,您应该手动调用startup()

如果您想检查小部件是否已经启动,您可以检查小部件内的_started 属性。这是在startup() 方法中设置的。

【讨论】:

我可能需要对 _started 添加一个检查,但这是一种不好的做法,因为它被标记为私有。 你说得对,我不会轻易使用它。如果您愿意,可以在小部件中定义自己的启动变量,只需在 startup() 中将其设置为 true 并确保调用 this.inherited【参考方案2】:

自动启动小部件是一个很好的功能,实际上如果您遵循启动方法的标准代码,您不必担心启动被调用两次:

startup : function() 
    if (!this._started) 

        //your startup code at here

        this.inherited(arguments);
        this._started = true;

    
,

【讨论】:

啊,我明白了,在小部件内部检查_started,很有趣。我会试试的。 顺便问一下,您在哪里找到“启动的标准代码”文档,上面给出了类似您的示例,最好有进一步的参考? @Jez ,dojo 源码中有很多这种用法,例如可以在 dijit/tests/_WidgetsInTemplateMixin.html 或 dijit/_WidgetBase.js 中找到 我知道你为什么要设置_started,但我不确定开始设置由超类更改的私有变量是否是一种好习惯。即使我们知道该类型无论如何都是布尔值,dojo 更新也有可能更改其类型,从而可能导致意外行为。我会依赖超级声明和定义_started,然后检查它。

以上是关于Dojo 1.9:当父窗口小部件启动时,placeAt 自动调用启动的主要内容,如果未能解决你的问题,请参考以下文章

Dojo 小部件在响应 XhrPost 时返回时不呈现

Dojo 选择小部件验证

Dojo Validation TextArea 小部件在无效时如何突出显示?

自定义小部件内的 dojo 小部件的可寻址性

Dojo 和 Ajax - 渲染小部件

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