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
在第一次启动后无论如何都会设置为true
或false
,只要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 自动调用启动的主要内容,如果未能解决你的问题,请参考以下文章