• 简单分析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', 
     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)            

     

     

     

  • 相关阅读:
    HBase学习笔记-基础(一)
    系统架构师之旅(一)——软件架构设计:程序员向架构师转型必备总结
    高效程序员的特征:聪明,懒惰
    TOMCAT源码分析(启动框架)
    Java线程池的原理及几类线程池的介绍
    Java 并发:Executors 和线程池
    Memcache基础教程
    发邮件
    图片验证码
    上传图片添加水印
  • 原文地址:https://www.cnblogs.com/yql1986/p/1986296.html
Copyright © 2020-2023  润新知