您的位置:首页 > 其它

简单分析Ext.ComponentMgr 函数

2011-03-16 17:34 316 查看
在找网上找了一下关于这个函数的大致介绍:

提供一个页面中所有组件的一个注册表( Ext.Component 的实例,或者任何子类),这样可以通过 component id 方便此访问它们 此对象也提供了可用Componentclasses的一个注册表 ,以便于记忆的字符串为key,叫做Component的 xtype. xtype . 当创建一个完整的、包含配置项的对象时,它为一个完全使用Ext的页面 提供了一种避免实例化子组件方法。子组件可以被简单指定为一个配置对象 ,只要指定正确的xtype ,这样当Component需要渲染时, 可以找到正确的类型进行懒初始化。

今天在分析Ext.form.FormPanel组件,在一地方卡了很长时间,其中就涉及到Ext.ComponentMgr。特在这里记下,免得以下又会被卡住,也希望看到此篇文章的同行有所收获

<script type="text/javascript">
Ext.onReady(function () {
var panel = new Ext.form.FormPanel({
renderTo: 'formPanel',
width: 400,
height: 500,
layout: "form",
items: [{
xtype:'fieldset',
columnWidth: 0.5,
title: 'Fieldset 1',
collapsible: true,
autoHeight:true,
defaults: { anchor: '-20' // leave room for error icon },
items: [
{xtype:'customType-0', fieldLabel: 'Field 0' },
{ xtype:'customType-1', fieldLabel: 'Field 1' },
{ xtype:'customType-2', fieldLabel: 'Field 3' }
]
}]
});
}); </script>




图(1)FormPanel类的继承结构图

当实例化FormPanel则会调用Ext.Component的constructor,如果你不知道为什么,可以先看下之前的文章就会明白.当调用Ext.Component的constructor时候

Ext.Component = function(config){

//...

this.initComponent();

//...

}


this.initComponent将会调用FormPanel的initComponent,这将会沿着FormPanel的继承链一直向上回溯至Ext.Component 的initComponent方法,在这一系列调用initComponent方法的过程之中我们将目光锁定到Ext.Container的initComponent方法

Ext.Container = Ext.extend(Ext.BoxComponent, {

//...

initComponent:function(){

//...

var items = this.items;
if(items){
delete this.items;
this.add(items);
}
},
add : function(comp){
this.initItems();
var args = arguments.length > 1;
if(args || Ext.isArray(comp)){
var result = [];
Ext.each(args ? arguments : comp, function(c){ result.push(this.add(c)); }, this);
return result;
}

var c = this.lookupComponent(this.applyDefaults(comp));

//...
},
applyDefaults : function(c){
//...
},
lookupComponent : function(comp){

if(Ext.isString(comp)){

return Ext.ComponentMgr.get(comp);

} else if(!comp.events){

return this.createComponent(comp);

}
return comp;

}, createComponent : function(config, defaultType){

if (config.render) {

return config;

}

var c = Ext.create(/*省略*/);

//...

}

//...

});


当调用Ext.Container的initComponent方法时候,将会牵扯到一系列的方法的调用,代码如上

当最开始调用this.add(items)时,此时的this的可执行上下文环境是panel( var panel=new Ext.form.FormPanel(/* ... */); ),此时items的xtype为fieldset



图(2)

接下来进入到Ext.Container的add函数中Ext.isArray(comp)显示是成立的,从图(2)就能看得出来。接下是Ext.each方法调用result.push(this.add(c))将会递归调用add

方法



图(3)

接上面,当递归调用add时传的参数截图如图(3) if(args||Ext.isArray(comp)){/* ...*/} 很显然不会执行,这样程序就执行到 this.lookupComponent(this.applyDefaults(comp)), 执行this.lookupComponent(/* ... */)方法,Ext.isString(comp)返回false 因为comp是object,因此将调用this.createComponent(comp),进入到方法。我们把目光锁定到Ext.create方法上,由于Ext.create = Ext.ComponentMgr.create 下面是这个函数的源码

Ext.ComponentMgr = function(){

//...

return {

create : function(config, defaultType){

return config.render ? config : new types[config.xtype || defaultType](config);
}

//...
};

}()


看上面的代码出现了new,当返回的时候this的可执行上下文环境就发性了变化,将不再是之前的panel了,而是新创建的Fieldset。当递归调用结束返回到Ext.Component中的this.add(items)时候,由于this的可执行上下文环境发现了变化,此时items截图如下



图(4)

从又会重复之前的动作。



图(5)

IE提示出现以上错误,crtl+G快速定位到10462行



图(6)

用VS调试



图(7)

以上是new types[/* ...*/](config)中的types的一部分截图,而此时config.xtype为"customType-0" 在types中没有,理所当然要报错,因为自己打算写相应的扩展,故用了xtype分别为"customType-0","custom-1","custom-2"。看到types数组中有许多项,我在Ext.ComponentMgr函数翻了半天,就是不明白这么多项是怎么来的,百思不其解???

Ext.ComponentMgr = function(){
var all = new Ext.util.MixedCollection();
var types = {};
var ptypes = {};
return {

//...

all : all,
types : types,
ptypes: ptypes
//...
}
}();


看到Ext.ComponentMgr函数后面的括号,想到该函数在加载之后会立刻执行。以下是该函数执行完之后的截图



图(8)

执完该函数完之后,types中一项也没有,感觉太奇怪了,继续单步调试下去到了 Ext.reg('component', Ext.Component);

因为 Ext.reg = Ext.ComponentMgr.registerType;

Ext.ComponentMgr = function(){

//...

return {

//...

registerType : function(xtype, cls){
types[xtype] = cls;
cls.xtype = xtype;
}

//...
};
}();


看到这个registerType函数之后,一下子就明白了 当执行完 Ext.reg('component', Ext.Component);



图(9)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: