日期:2014-05-16  浏览次数:20378 次

ExtJS4.0源代码分析----类系统之类的创建
ExtJS4.0的类系统是整个框架的基础且核心的架构设施,其它所有的功能扩展都是建立在类系统上的。在ExtJS4.0中,类系统相对以前的版本有大幅度的改变,在以前的版本中,定义一个新类是在一个已经存在的类如Object的基础上调用
var myClass = Ext.extend(Object, { ... });
进行扩展而来,这样我们不能方便的给新建的类添加statics属性或方法及mixins等功能,且新建的类需要依赖Object等这些要继承的类,Object也会递归的依赖它的父类,如果这些类未创建就会出现错误,所以在以前的版本中干脆把整个ext-all.js在一开始就全部加载进来并创建整个框架中定义的所有类,这样即使你在一个应用中只使用ExtJS的一个类也要把整个ExtJS的类加载进来,大大将低了程序运行效率。在extjs4.0中通过使用
Ext.define(className, members, onClassCreated);
来创建类解决了上面的问题。其中className是创建的类的名字,是String类型的;members是给要创建的类添加的配置信息,主要包括requires(要求使用的类),extend(要继承的类),mixins(向创建的类中要掺进其它类的信息),config(给创建的类配置属性方法等),statics(给类增加静态属性或方法),以及其它的一些属性方法等信息,这些配置信息在后面会详细说明;onClassCreated是类创建后的回调函数。

在ExtJS4.0中,与类创建相关的js文件主要有src/core/src/class中的Base.js,Class.js,ClassManager.js,Loader.js。其中Base.js定义了Base类,Base类是ExtJS4.0中所有通过Ext.define定义的类的直接或间接父类,Base类中定义了一些通用的实例与静态属性与方法;Class.js文件中定义了Class类,所有通过Ext.define定义的类都是Class的实例(其实是Class构造函数中的newClass类);ClassManager.js文件中定义了ClassManager单例,它主要负责对类的管理,如类的创建与类实例化等;Loader文件中定义了Loader单例,实现了ExtJS4.0中动态加载类的功能。

以ExtJS中的Component类为例,它的类创建代码如下:
Ext.define('Ext.Component', {

    /* Begin Definitions */

    alias: ['widget.component', 'widget.box'],

    extend: 'Ext.AbstractComponent',

    requires: [
        'Ext.util.DelayedTask'
    ],

    uses: [
        'Ext.Layer',
        'Ext.resizer.Resizer',
        'Ext.util.ComponentDragger'
    ],

    mixins: {
        floating: 'Ext.util.Floating'
    },

    statics: {
        // Collapse/expand directions
        DIRECTION_TOP: 'top',
        DIRECTION_RIGHT: 'right',
        DIRECTION_BOTTOM: 'bottom',
        DIRECTION_LEFT: 'left',

        VERTICAL_DIRECTION: /^(?:top|bottom)$/
    },

    resizeHandles: 'all'
  }
);

一个类创建前与创建后分别会有前置处理器与后置处理器对类进行装饰以增强类的功能,下面一张图片对类的创建过程作了一个详细的说明:
类创建前会有loader,extend,mixins,config,statics对类增加配置信息,且这些preprocessor是按顺序进行的,postprscessor主要包括alias(为类设置别名)与legacy等。

Ext.define实际上是ClassManager中的create方法的别名,ClassManager是一个单例,里面主要定义了与类的创建(create)与实例化类(instantiate)相关的方法。所以
Ext.define(className, data, onClassCreated);
实际上是调用了
ClassManager.create(className, data, onClassCreated);
。在此方法内部,会先将className添加到data,之后会new一个Class并返回,所以可以说Ext.define出的类都是Class这个类的实例(其实new Class后返回的是其内部的newClass类),下面是裁剪后的代码:
create: function(className, data, createdFn) {
            var manager = this;

            data.$className = className;

            return new Class(data, function() {
                var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
                    registeredPostprocessors = manager.postprocessors,
                    index = 0,
                    postprocessors = [],
                    postprocessor, postprocessors, process, i, ln;

                delete data.postprocessors;

                for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
                    postprocessor = postprocessorStack[i];

                    if (typeof postprocessor === 'string') {
                        postprocessor = registeredPostprocessors[postprocessor];

                        if (!postprocessor.always) {
                            if (data[postprocessor.name] !== undefined) {
                                postprocessors.push(postprocessor.fn);
                            }
                        }
                        else {
                            postprocessors.push(postprocessor.fn);
                        }
                    }
                    else {
                        postprocessors.push(postprocessor);
                    }
                }

                process = function(clsName, cls, clsData) {
                    postprocessor = postprocessors[index++];

                    if (!