Ext4.x 之了解基本体系结构

来源:互联网 发布:麻瓜网络 编辑:程序博客网 时间:2024/06/10 14:42

对于ExtJS4.x版本,对原始ExtJS3.x版本进行大量的底层重构,但是对于最基本的前端底层体系结构任何JS框架都不会轻易改变.下面就简单普及下前端知识吧。

对于编码层次的体系设定(经典的三层架构):

    第一, base层 (框架通用基础层,一般会对JS原生对象扩展很多好用的方法)

    第二,commons层 (框架的通用UI组件层, 一般会实现很多通用的组件 ,提供给page层调用)

    第三,page层 (页面展现层,这个就是根据具体的业务逻辑自己去实现了)

嗯 ,这里要说的事儿其实很简单呢!加入你做过前端开发,很容易理解,如果不理解的话推荐网上找找资料或者看下相关的技术书籍。

也就是说我们在设计自己的前端架构时候只需要按照这个套路就可以写出自己的JS库。

嗯当然对于base层一般不会去用纯js去写,应该使用比较成熟的库作为base,

例如(YUI、JQuery),然后把一些能封装的自己封装下以便于更舒爽的被开发者所使用。

common层呢就是希望能写一些通用的组件,比如accordion菜单、下拉框、UI表格等等

(当然你可以理解Ext的组件其实就是这一层面上,他自己的组件都是按照自己的一套面向对象基础架构去扩展的)。

page层就没什么可说的了,我们在真正编写JSP页面的时候(哦首先说明我是搞java的)可以直接使用这些common组件。

详细说下base层都需要做些什么事儿,主要分三点吧。

    第一点,就是对原生javascript对象和方法的扩展。

    第二点,对于偏向UI框架体系的JS库,封装一系列DOM操作也是必然。

    第三点,框架对于事件的支持,必须实现一套完全屏蔽浏览器差异的事件体系。

嗯,有了这个基础知识普及,那么Ext的基础架构其实就是做的这些事儿


1:首先肯定要说的就是Ext基本文件。在4.x版本中提供了俩个基本文件Ext.js和Ext-more.js,位置在源码包下(src下)


Ext.js中提供了一个Ext框架最基本方法,Ext中几乎所有的扩展都采用这个方法,那就是大名鼎鼎的Ext.apply了,

呵呵,此apply并非函数原生的apply方法,不是为了绑定作用域。

这个方法提供了对于对象的扩充功能,这个方法的实现非常的简单且经典(原因是实现的很严谨)


     Ext.apply = function(object, config, defaults) {        if (defaults) {            Ext.apply(object, defaults);        }        if (object && config && typeof config === 'object') {             var i, j, k;            // 就是一个枚举 然后进行对象属性的copy,把新的属性赋给这个对象而已 如果属性重复就覆盖掉            // 如果你不理解的话 需要补一补JS基础了,对象的天然hash特性            //(也就是key不能重复 YUI早期有个去除数组中的重复项的方法就是利用这个来做的)            for (i in config) {              object[i] = config[i];             }                                  //这里要说下enumerables这个变量了的作用了            //我只简单说明其目的是为了用enumerables判断当前浏览器是否支持for in 枚举            //且把js原生对象的方法枚举出来            //当然这个enumerables在Ext.js文件的开头部分我没有把代码都贴过来            //..下面注释的代码就是             /**                  //初始化一个变量为true                var enumerables = true,                               //测试对象 里面就一个原生对象的属性toString                enumerablesTest = {toString: 1};                                 //进行for in 枚举测试 看看能不能把里面的toString枚举出来                 //如果能就说明当前浏览器可以枚举原生对象的key                for (i in enumerablesTest) {                              enumerables = null;                   }                //这些都是js原生对象的key 可以说是一个js对象必须应该有的key                if (enumerables) {                                        enumerables = ['hasOwnProperty', 'valueOf',                        'isPrototypeOf', 'propertyIsEnumerable',                         'toLocaleString', 'toString', 'constructor'];                  }            */                        // 如果不能枚举出来 就把一个js对象原生的key都copy给新对象            if (enumerables) {                 // 至于为什么使用递减的方式循环,因为js递减的效率比正常递增要高                for (j = enumerables.length; j--;) {                     k = enumerables[j];                     // hasOwnProwperty这些基本的js方法 如果你不熟悉 应该找本js书恶补了.                    if (config.hasOwnProperty(k)) {                          object[k] = config[k];                     }                 }                 }         }         return object;     };

嗯,看完了这个简单的apply方法之后你就应该明白ext的apply方法的含义了吧。

继续,再有就是通过Ext.apply方法封装了一些常用的其他方法,

如:applyIf、iterate、extend、override、typeOf、isEmpty、isDefined、isArray....(这些方法除了extend方法外都非常简单,请自行研读,extend方法请参考相关JS继承的资料)

简单说明下用法:
applyIf :和apply类似 只不过是如果源对象存在的key就不进行覆盖其value值 保留原对象key的value值而已

iterate:看名字就知道是进行遍历对象的了,这个方法既可以遍历纯粹的“{name:value}”形式对象 也可以遍历数组

extend:这个涉及到js继承了 主要就是一些空函数转换啊 一些技巧如类模板继承 原型继承等 不多说了 有兴趣看底层 查阅相关资料即可

override:覆盖对象中的某一个方法的 有点类似java的override 呵呵

typeOf:还需要我多说么 和原生js里的typeof使用类似 源码非常简单

isEmpty、isDefiend、isArray.....这些方法不需要我说了 自己看源码。

对于Ext-more.js这个文件,一上来就使用了Ext.apply这个函数用于扩展功能了,嗯,你懂得!

然后扩展了对于浏览器的兼容性和类型判断、DOM对象缓存机制、一系列操作DOM元素的简单常用方法、

Ext.id()方法等等..有童鞋问这个方法有什么用呢,你不需要知道,一般你永远都用不到这个方法,

因为这个方法是给Ext组件内部的html标签使用的,也就是最底层HTML标签元素id生成策略。

总结一句话,这个文件就是对Ext.js的一个补充嘛!以上就是Ext的俩个核心文件的概述。



2:Ext对原生javascript的扩展

Ext对于原生Javascript对象的扩展使用沙盒模式对原生JS对象进行扩展,

与旧版本的直接使用prototype进行扩展完全不同,其目的就是 为了你在引入其他JS库的时候避免产生冲突问题,

这点Ext考虑的非常全面。你可以根据需要放心大胆的一起使用Jquery等JS库。

在源码包下(src下)的lang包里我们找到了7个js文件:Array.js Date.js Error.js Function.js Number.js Object.js String.js

也就是Ext对于JS原生对象的扩展文件。随便打开一个文件,Array.js 在里面我们可以看到这样的代码

ExtArray = Ext.Array = {...};

我们明白了其实就是在Ext这个大的单体对象下追加一个Array对象而已,里面就是对应的扩展内容。

其他几个文件当然也是对原生对象的扩展了,不做解释了。

特殊说明一下Error.js里面Error这个对象就是一个Exception处理器,在你运行Ext代码时如果出现异常,就会使用其内部raise方法输出异常信息并告知开发者。

当然这些对JS原生对象扩展的类都非常好用,我们可以更舒心的操作数组、字符串、日期、数组、对象、函数等等...其源代码也非常的简单,

相信有一点JS基础的你看懂他们都不成问题。

3:然后我们来谈谈Ext的DOM封装。

对于Ext这样的富客户端Ajax框架,我们应该可以预期得到Ext对于DOM的封装之强大复杂。

首先说明一下Ext把原生的DOM对象封装成了Ext.dom.Element这个类,以提供操作DOM丰富的方法。

你可以使用其内部实现的166个方法、35个事件等...呃我还有点疑问呢,

记得4.1版本的时候是178个方法,怎么4.2版本反而少了呢?其实很多方法被4.2版本分出来了。

原来多了一个Ext.dom.Layer的新类,里面主要是对元素样式和特效的操作,

如设置元素样式,尺寸; 淡入淡出效果、隐藏显示效果、滑上滑下效果等等...

哇!这么一看操作DOM就有300多个方法了,原来4.2版本真心又强大了好多而且细节方面做的更好了。

这个已经足够强大了,但是他还不满足现状,我们知道DOM操作是非常昂贵的,

所以内部使用了一些经典的设计模式,如享元模式来构造简单的Ext.dom.Element.Fly对象

我们同样可以拿它来当做Ext.dom.Element对象去使用,

只需要调用Ext.fly这个函数即可(但是需要注意的问题是如果多次使用同一个节点的时候,就别用fly方法了,

会出现永远只操作一个元素的问题,

所以你还是需要使用Ext.get这个方法),提到Ext.get这个方法,就不得不说Ext.get这个方法的缓存机制,

他会把构建好的Ext.dom.Element放到缓存里以便以后频繁的操作和使用,大大的节省了内存。

如果你想直接从页面获得原生元素,可以直接通过dom属性获得,或者直接使用Ext.getDom这个方法即可。

对于Ext.dom.Element这个类,Ext还提供了俩个助类,DomHelper、DomQuery我们可以更方便的操作DOM元素。

Ext还提供了Ext.dom.CompositeElement和Ext.dom.CompositeElementLite这俩个类,他们都返回数组

只不过CompositeElement每一个元素里装的是Ext封装好的Ext.dom.Element对象,而CompositeElementLite返回原生的DOM元素。


4:Ext框架对于事件的支持

Ext事件的封装是非常强大的,提供了俩套封装事件实现 :第一封装浏览器内置事件,屏蔽浏览器差异; 第二封装自定义事件,你可以扩展自己的事件。

并且这俩套都做了统一的接口处理,我们可以使用统一的接口去添加内置事件和自定义事件,非常好!

Ext.EventManager这个类,就是对浏览器内置事件的一个完美的封装,屏蔽了浏览器间的差异。

我们紧紧使用Ext.EventManager.on()或un()方法即可添加和移除事件 Ext.util.Observable这个类,就是对用户自定义事件的一个封装,

你可以利用内部方法添加自定义事件。并且所有的Ext组件都会混入(多继承)Ext.util.Observable这个类。


5:对于EXT的定义和创建类。define和create方法

嗯!这个ExtJS4.X中,主要就是重构这个功能体系,相信你应该清楚原生JS怎么去写一个类的定义和实例吧。

无非就是 var Person = function(name.sex){....};  var p = new Person('张三',20);   之流.... 嗯!继续说Ext。

Ext.define方法我们可以定义一个类; Ext.create方法我们可以创建一个类的实例对象; 这与之前的3.4版本完全不同。

define方法的实现异常的复杂,不再是以前版本简简单单的Ext.extend了。有人会问why? 答案很简单:就是为了可扩展性更强!

ExtJS4.X中我们会看到Ext.Class这个类,这个类是干什么的? 他是创建类的类,就是你在使用define的时候表示定义一个类,

需要按照Ext.Class这个类的配置去完成,不然你定义的Ext类没法正常运行。对于Ext.Class的配置项(config)说明:     

extend:用于继承    

alias:类的别名        (给组件定义xtype:widget.name,其中name的值就为xtype的引用值)    

alternateClassName:备用名,与alias差不多   

requires:需要使用到的类名数组,在动态加载时会根据该属性去下载类,注意需要的类是在当前类之前被加载   

uses:与requires类似 但是被引用的类可以在该类之后才加载   

constructor:构造器属性,一般用来初始化类的配置和调用其父类的方法    

mixins:混入属性,多继承   

config:定义类的配置项,会把config里的每个属性加上get和set方法   

statics:定义静态方法,属性不能被子类继承  

 inheritableStatics:与statics类似,但是其属性可被子类继承   

singleton:设置该类为单件模式

嗯!这就是define方法的配置项了,当然没有什么是必须配置的;我们的类就定义完成了,当然之前说采用define是为了可扩展性更强,原因呢?

之前提过define方法的实现异常的复杂,这点从配置项就可以感觉到,创建一个类可能经过一些列的操作,

去检查到底都配置了哪些配置, 然后对应的给所配置的信息添加类的相关操作。

简单说明:一个类从定义开始到结束期间经过13个处理器,最后完成类的定义,我们分三步走。

第一步:(define开始):ClassName -> Loader -> Extend ->   (这三个处理器是required,也就是一个新类必须走的处理器)

第二步:Statics -> InheritableStatics -> Config -> Mixins -> Singleton -> Alias -> Xtype -> AlternateClassName -> Uses (这9个处理器需要根据你的配置项检查是否执行)

第三步: ClassManager (这个新定义的类最后注册给classManger(Ext中类的管理者)去交给管理起来,多贴心啊)

嗯!每一个处理器都是做什么用的?不好意思自己看api或google吧,非常easy的东西,这里只解释前三个处理器。

ClassName处理器 :解析你定义的类名的。

Loader处理器:动态加载的(大家都知道ExtJS4.X有动态加载组件的机制)。

Extend处理器:用于继承的,有人说我自己定义的类如果没继承任何类,为什么必须走这个处理器呢? 如果没有配置extend,默认会继承Ext.Base,这是Ext所有类的根基类(类似JAVA的Object)。所以这个处理器也必须会走的。

相信你差不多明白为什么采用define方法定义类能使其扩展性更强了,以后如果我新加一个处理器,直接在13个处理器之中添加即可。 


最后我简单总结下:Ext的基础架构设计 = (添加框架的内部基本方法、原生JS对象扩展) + 封装操作DOM + 封装事件机制 + 类的创建于管理机制;

0 0
原创粉丝点击