您的位置:首页 > Web前端 > JavaScript

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

2015-02-27 15:35 447 查看

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文件中.

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这个方法.

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() {.......}) ,执行第三个参数,即回调函数.

本文先讲到这里,接下来就是分析这些类的预处理器究竟做了哪些事情,放到第二篇在继续.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: