简单分析Ext.ComponentMgr 函数

在找网上找了一下关于这个函数的大致介绍:

      提供一个页面中所有组件的一个注册表( 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)            

 

 

 

posted @ 2011-03-16 17:34  来自非洲大草原的食人虎  阅读(2021)  评论(1编辑  收藏  举报