Extjs4 源码分析系列一 类的创建过程

Extjs源码分析

  第一次写博客,以下是我个人阅读了Extjs的源码,借鉴了Extjs权威指南这本书的部分内容,和自己的一些调试,写出了我自己对Extjs的架构和源码级别的一些理解和认知.写的不好的地方,还请各位看官多多包涵,提出宝贵意见.

本文省略了源码中的一些调试语句,只针对关键部分进行讲解.

从Ext的四个基础的classs开始,先看src/class/目录下面的四个js文件:Base.js,Class.js,ClassManager.js,Loader.js.

Base.js中定义了 Base = function(){},也就是说Base是一个function,然后又调用Ext.apply(Base, {}),给function Base 添加了一些属性和方法,可以说Base是所有类的基类.ClassManager.js这个js文件是管理Ext的类系统的,Class.js是用来生成类的,Loader.js是用来动态加载js文件的.

我们先从这里开始分析,一般在Extjs中,我们常常这样定义一个类Ext.define(‘AAA’,{}),Ext.define这个方法在ClassManager.js文件中.

1
2
3
4

define: function (className, data, createdFn) {
//调用Manager的静态方法create
return Manager.create.apply(Manager, arguments);
},

这里又调用了Manager 的create方法,第一个参数为class的名字,第二个 参数为传入的配置对象,第三个参数为创建了class后的回调函数.
复制代码

create: function(className, data, createdFn) {

        //ctor指向一个function constructor
        var ctor = makeCtor();
        if (typeof data == 'function') {
            data = data(ctor);
        }
        data.$className = className;
        //调用 Class.js文件的 Class的构造方法
        //第三个参数是onCreated
        return new Class(ctor, data, function() {.....});

}

复制代码

值得注意的是makeCtor这个方法.
1
2
3
4
5
6
7

function makeCtor () {
function constructor () {

        return this.constructor.apply(this, arguments) || null;
    }
    return constructor;
}

这里是一个闭包,返回了 function constructor,这里的用途是在实例化class的时候执行Class的构造方法用的,

更详细的我会在Ext.create方法的源码解读时来分析.接下来给data,也就是传入的配置项添加了一个属性$className,保存类名,接下来new Class(ctor, data, function() {…….}) ;Class这个类的源代码在Class.js中,我们暂时先不去管最后一个参数,也就是那个回调函数,这个在类创建的最后一步才会体现出他的作用.

Class.js中定义了 Ext.Class = ExtClass = function(Class, data, onCreated) {…},之后又Ext.执行了apply(ExtClass, {}),给ExtClass这个function添加了一些静态方法,包括了后面需要调用的create方法.下面我们来看一下 ExtClass中又做了些什么?
复制代码

Ext.Class = ExtClass = function(Class, data, onCreated) {
//这是用来调整参数位置的,new Class(ctor, data, function() {},如果ctor不是function 需要调整参数,这里 不去关注
if (typeof Class != ‘function’) {
onCreated = data;
data = Class;
Class = null;
}
    
if (!data) {
data = {};
}
//调用Class的静态方法create
Class = ExtClass.create(Class, data);
//执行Class的处理器
ExtClass.process(Class, data, onCreated);

    return Class;
};

复制代码

这里看到了执行了ExtClass的create方法和process方法.先来看create方法,这里很简单,就是把Ext.Base这个类的静态方法和属性全都复制到传入的class中,这个class实际上就是makeCtor()这个方法返回的function constructor,源代码如下:
复制代码

create: function(Class, data) {
var name, i;

        if (!Class) {
            Class = makeCtor(
                //<debug>
                data.$className
                //</debug>
            );
        }

        //拷贝Ext.Base类的静态方法到子类Class上
        for (i = 0; i < baseStaticMemberLength; i++) {
            name = baseStaticMembers[i];
            Class[name] = Base[name];
        }

        return Class;
    }

复制代码

接下来比较重要的是process方法,这个方法比较长,乍看比较复杂,其实仔细看看也很容易理解.

先贴上源代码:
复制代码

process: function(Class, data, onCreated) {
//ext 预制的几个处理器 ,有三个必须执行的是 className ,loader,extend
/**
*
defaultPreprocessors:
0: “className”
1: “loader”
2: “extend”
3: “statics”
4: “inheritableStatics”
5: “config”
6: “mixins”
7: “alias”
length: 8
registeredPreprocessors:

            registeredPreprocessors: Object
                alias: Object
                    fn: function (cls, data) {
                    name: "alias"
                    properties: Array[2]
                    __proto__: Object
                className: Object
                    fn: function (cls, data) {
                    name: "className"
                    properties: true
                    __proto__: Object
                config: Object
                    fn: function (Class, data) {
                    name: "config"
                    properties: Array[1]
                    __proto__: Object
                extend: Object
                    fn: function (Class, data, hooks) {
                    name: "extend"
                    properties: true
                    __proto__: Object
                inheritableStatics: Object
                    fn: function (Class, data) {
                    name: "inheritableStatics"
                    properties: Array[1]
                    __proto__: Object
                loader: Object
                    fn: function (cls, data, hooks, continueFn) {
                    name: "loader"
                    properties: true
                    __proto__: Object
                mixins: Object
                    fn: function (Class, data, hooks) {
                    name: "mixins"
                    properties: Array[1]
                    __proto__: Object
                statics: Object
                    fn: function (Class, data) {
                    name: "statics"
                    properties: Array[1]
                    __proto__: Object
         */
        var preprocessorStack = data.preprocessors || ExtClass.defaultPreprocessors,
            registeredPreprocessors = this.preprocessors,
            hooks = {
                onBeforeCreated: this.onBeforeCreated
            },
            preprocessors = [],
            preprocessor, preprocessorsProperties,
            i, ln, j, subLn, preprocessorProperty;

        delete data.preprocessors;

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

            if (typeof preprocessor == 'string') {
                preprocessor = registeredPreprocessors[preprocessor];
                preprocessorsProperties = preprocessor.properties;

                if (preprocessorsProperties === true) {
                    preprocessors.push(preprocessor.fn);
                }
                //如果preprocessorsProperties 不是true,是数组的话
                else if (preprocessorsProperties) {
                    for (j = 0,subLn = preprocessorsProperties.length; j < subLn; j++) {
                        preprocessorProperty = preprocessorsProperties[j];
                        //并且在data中配置了该处理器的key,如inheritableStatics
                        if (data.hasOwnProperty(preprocessorProperty)) {
                            preprocessors.push(preprocessor.fn);
                            break;
                        }
                    }
                }
            }
            else {
                preprocessors.push(preprocessor);
            }
        }
        //onCreated是ClassManger.js中  create 方法  return new Class(ctor, data, function() )的第三个参数
        hooks.onCreated = onCreated ? onCreated : Ext.emptyFn;
        hooks.preprocessors = preprocessors;
        //执行处理器
        this.doProcess(Class, data, hooks);
    }

复制代码

首先判断配置项中是否配置了preprocessors属性,如果没有的话采用默认的预处理器栈,

这是一个数组[‘className’,’loader’,’extend’,’statics’,’inheritableStatics’,’config’,’mixins’,’alias’],registerPreprocessors的值通过debug可以看到如下图

registeredPreprocessors: Object
alias: Object
fn: function (cls, data) {
name: “alias”
properties: Array[2]
proto: Object
className: Object
fn: function (cls, data) {
name: “className”
properties: true
proto: Object
config: Object
fn: function (Class, data) {
name: “config”
properties: Array[1]
proto: Object
extend: Object
fn: function (Class, data, hooks) {
name: “extend”
properties: true
proto: Object
inheritableStatics: Object
fn: function (Class, data) {
name: “inheritableStatics”
properties: Array[1]
proto: Object
loader: Object
fn: function (cls, data, hooks, continueFn) {
name: “loader”
properties: true
proto: Object
mixins: Object
fn: function (Class, data, hooks) {
name: “mixins”
properties: Array[1]
proto: Object
statics: Object
fn: function (Class, data) {
name: “statics”
properties: Array[1]
proto: Object

这是具体的值.

接下来就是循环 preprocessor数组,在根据数组的值作为key,在registerProprocessor中找到,然后判断处理器的properties的值是否为true,如果为true,是一定要先执行的处理器,默认有三个预处理器:className,loader,extend,如果preprocessorsProperties 不是true,是数组的话,那么久需要判断出入的配置项是否配置了该处理器的配置,如果配置了的话,也需要push到preprocessors数组中,最后添加到hooks对象上,调用this.doProcess(Class, data, hooks),注意这里的this指向的是function ExtClass,也就是调用ExtClass的静态方法doProcess.

下面在看doProcess的源代码:
复制代码

doProcess: function(Class, data, hooks) {
var me = this,
preprocessors = hooks.preprocessors,
preprocessor = preprocessors.shift(),
doProcess = me.doProcess;

        for ( ; preprocessor ; preprocessor = preprocessors.shift()) {
            // Returning false signifies an asynchronous preprocessor - it will call doProcess when we can continue
            if (preprocessor.call(me, Class, data, hooks, doProcess) === false) {
                return;
            }
        }
        //执行Ext.Class的静态方法 onBeforeCreated
        hooks.onBeforeCreated.apply(me, arguments);
    },

复制代码

从hooks.preprocessors 数组中依次弹出处理器,并调用处理器的方法,传入ExtClass,Class,data配置,hooks,和doProcess方法,如果执行处理器的执行结果为false,就返回,不在执行后面的处理器,class初始化失败.最后执行hooks.onBeforeCreated方法,这个就是之前我们说的new Class(ctor, data, function() {…….}) ,执行第三个参数,即回调函数.

转自博客园”ace1234”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值