DOJO组件生命周期the life cycle of dojo widget
分类:Dojo作者:编程之家用户
在使用dojo过程中对于组件生命周期一直不是特别清楚,官方文档写的也不够恰当,所以特地研究了一下,做了公司内部培训,这就是为什么有了这篇文章。本文主要通过读DOJO的源码以及源码中的注释来了解DOJO组件的生命周期。今天分享给大家,供大家参考,不当之处欢迎大家指教。
1.组件生命周期预览
dojo组件生命周期比较重要的是以下几个部分
调用constructor方法
将创建组件时指定的参数mixin到组件实例中
执行postMixInProperties方法
执行buildRendering方法(创建组件的DOM对象)
复制组件对象中的属性到DOM对象中
执行postCreate方法
执行startup方法
组件销毁时执行destroy方法
注:
constructor方法在new后者parse时调用。
startup方法可由外层组件或者placeAt或者addChild再或者手动调用。
其他的方法均是在组件的create方法中调用。
2.各方法作用及调用时机
2.1constructor
创建一个组件对象时调用,可以做一些变量初始化.值得注意的是此时传递给组件的变量还没有mixin到组件对象中。
2.2postMixInProperties
在执行postMixInProperties方法之前传递给组件对象的属性已经mixin到组件对象中,可以在create方法中找到如下代码:
-
- if(params){
- this.params=params;
- lang.mixin(this,params);
- }
- this.postMixInProperties();
但是此时组件的DOM对象还没有创建,如果想在DOM对象创建之前修改组件对象的属性在这个方法中做是适合的。但是值得注意的一点在执行完buildRendering之后且在执行postCreate方法之前会执行_applyAttributes方法,而_applyAttributes方法中会将创建组件对象时传递的参数再一次覆盖到组件对象中(在执行postMixinProperties方法前已经覆盖过一次),所以在执行_applyAttributes之前做的相关属性修改都会失效。
//create方法中片段
- this.buildRendering();
- vardeleteSrcNodeRef;
- if(this.domNode){
- this._applyAttributes();
- varsource=this.srcNodeRef;
- if(source&&source.parentNode&&this.domNode!==source){
- source.parentNode.replaceChild(this.domNode,source);
- deleteSrcNodeRef=true;
- }
- this.domNode.setAttribute("widgetId",this.id);
- this.postCreate();
-
- for(varparaminthis.params){
- this.set(param,153); font-weight:bold; background-color:inherit">this.params[param]);
- }
注意:虽然在postMixinProperties方法执行前已经将创建组件时配置对象中的属性mixin到组件对象中,但是对这些属性进行更改是不恰当的,dojo会在执行完成postMixinProperties后做第二次属性覆盖。所以建议在postCreate中进行修改。
2.3buildRendering
这个方法的作用是创建组件的DOM对象,并将DOM对象的指针保存在this.domNode中。先来看一下执行完postMixInProperties方法且在执行buildRendering方法之前做了什么:
1)如果组件对象没有id则根据组件类名字(带命名空间)生成组件id。生成规则是将类名字中的点(.)替换为下划线(_),并根据当前实例是组件类的第几个实例生成相应的下标,id类似于dojox_slickgrid_slickgrid_0。如果声明组件时指定了DOM的id则组件的id使用DOM的id。id优先级规则为创建组件时指定的id>组件创建锚点的domid>自动生成的id。
2)将组件注册到dijit/registry模块中(registry.add(this);),这就是为什么能用registry.byId('组件id')获取到组件。
言归正传,接下来接着说buildRendering。buildRendering创建DOM对象分以下几种情况:
1)有模板。一般来说在有模板的组件都会mixin_TemplatedMixin模块,该模块重写了buildRendering方法,重写方法利用模板生成DOM对象。
2)没有模板,声明式创建或者程序式创建指定了组件放置的DOM,如newGrid({},"grid-idv")中的第二参数即为放置组件的锚点。此时将声明组件的DOM对象作为this,domNode。
3)没有模板,没有指定放置组件的DOM。此时生成一个DIVDOM对象作为this.domNode。
注:buildRendering方法的另一个作用是将组件对象中的baseClass追加给this.domNode。
模板中的data-dojo-attach-point='containerNode'有什么特殊用处?
当声明式创建有模板的组件时开始标签和结束标签中间包含的内容会自动包含进以'containerNode'为附着点的标签内,而且内容可以dojo组件。
在什么地方完成的上述操作?
在_TemplatedMixin的buildRendering中。
模板中的containerNode存在其他内容会怎样?
如果模板中存在其他内容,声明式开始标签和结束标签之间的内容将追加在containerNode模板内容之后。
特别说明:
_TemplatedMixin模块中的buildRendering方法可以缓存模板生成的DOM节点,但有两个前提条件,如下:
a)组件对象的全局属性_skipNodeCache为false。
b)模板中没有模板变量。
另外如果用templatePath指定模板而不是用templateString指定模板,_TemplatedMixin方法会将templatePath指定的模板缓存在templateString中。
2.4postCreate
这是一个常用的组件扩展点,执行这个方法的时候this.domNode已经被创建了,这个时候做事件绑定是合适的。虽然组件的DOM对象已经创建了,但是做尺寸相关的计算是有风险的,原因是执行该方法的时候this.domNode并不一定被添加到文档树中,外联样式不会对该DOM生效。
在执行postCreate之前会做如下操作:
1)将组件对象中的属性复制到this.domNode对象中
2)如果是声明式创建或者程序式创建并且指定了组件要放置的DOM描点则将this.domNode添加到文档中,如果程序式不指定组件要放置的DOM则不添加到文档中(这就是在postCreate中做尺寸计算存在风险的原因)。示例代码依次如下: