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

extJs 2.0学习笔记(组件总论篇)

组件正是extJs的亮点所在,像平常要用的Ext.Window、Ext.tabpanel都是我们最喜欢的好东西。要彻底弄清楚这中间的机制啊。
  我查到了一些参考资料:

Ext组件结构分析
Ext组件概述
Ext组件模型概况
Ext组件的生命周期
Ext.Component的Render方法详解
ExtJs实用开发教程
asp.net中使用JSON
Ex的树组件的使用(从底层到表现到异步加载)
  本来打算仔细分析一下Observable、Component、BoxComponent、Container这几个基类的源代码,但是不巧,正好看到了上面列出的教程中的“ExtJs实用开发教程”,这个系列教程写得太好了,以至于只要看一看教程就可以写出满足常见需求的代码来。而且,有了它,对于所有组件使用都有了一个大概映像。不至于不晓得如何下手,而非得去啃代码了。万岁啊。

  现在大概映像有了。继续看代码。

  Observable类是整个组件架构的最顶层的类。它的用途就是为组件提供统一的事件管理接口,有人问?怎么又是事件管理啊。 Ext.Element不是已经封装了事件管理的机制了吗?也有人问:不是有了Ext.Element了吗,为什么还要Ext.Component呢?其实这两个问题是一件事。

  Component是组件,组件不是一个元素,而是若干个元素的有机集合。Element的确是有事件,但是,组件的事件不同于元素的事件,它是一个更高级别的概念。

  Observable类没什么了不起的。事件管理吗?其本质就相当于c#/java中的容器类,原理就是内置一个数组或者是{},然后提供一个接口来add、remove、removeAll、find。这些东西在c#/java中早就炒得滚瓜烂熟了。而所谓的addEvents方法本质就是为一个map加了一群的key。找到代码,果不其然,就是依赖于this.events,它初始值为{}。它怎样实现事件的注册、反注册、事件包装呢?说出来也蛮容易。内部依托于一些容器(像数组、json对象),然后把所有的要监听的元素、监听元素的事件、事件处理函数、scope、options都保存在里面,时机一至就fireEvent了。怎么包装事件呢?那段代码我也没有去看了,方法无法两种:

  一、对于原本就有事件,类为对应元素创建一个默认处理函数,在这个处理函数里面会FireEvent对应元素此事件的事件处理函数。

  二、原本没有事件,像Ext.Component的beforeDestory之类的事件,这种事件就要自己在相应的地方手工FireEvent了。

  Ext.Component类,这是个很重要的类。对此我只有两点要介绍:

  一、关注它的config。组件构造函数的形参Ext.Element/String/Object。最为重要的是,形参可以是一个json对象,对于这个对象的各个成员的意义,这个是以后写代码的关键,例如:

  var wnd=new Ext.Window({titile:"这是伯平的标题栏",html:"这是窗口的内容!",width:400,height:300,layout:"fit"});

  上面代码是创建一个简单的div窗口,这是最普通的构造了,一般,还有一个items的成员,在它里面定义窗口的内容。items是一个数组,不过我与大伙一样都会产生一个疑问:只凭一个数组就能定义窗口吗?那些窗口成员的位置、大小怎么搞呢?关于样式,当然可以为每个数组成员填加一个成员 cls,用它设class。但是,布局呢?难道全部是absolute不成?有门的。你看上面定义窗口的时候不是有一个layout吗?fit是一种布局方式,它的作用是,容器中只能一个可见成员,且这个成员会填充满整个容器。关于布局类这些东西,作者是参考自java的swing了。现在,就连 dotnet的winforms也有类似的内容了。

  二、组件的统一管理,在Ext.Component的构造函数中有如下代码:

  Ext.ComponentMgr.register(this);

  extJs提供一个全局的类Ext.ComponentMrg。顾名思意:component manager。我跑过去看这个类的源代码,它内部用一个叫:Ext.util.MixedCollection的类来做容器,整个代码很少,加上注释才 100来行。register就是往Ext.util.MixedCollection里面add而己。当然,有add就有remove。这儿也有两个东西要注意:

关于Ext.getCmp(id)
getCmp : function(id){ return Ext.ComponentMgr.get(id); }这是Ext类中的代码,这个get现在能理解它的用途了吧,也就是说,只要一个组件被创建出来,它就会被加到这个容器中来,然后随时可以用它的id取出来继续用。所以,你甚至不用保存创建的组件的实例。可以直接用getCmp取出来。
关于Ext.reg它用于注册一种组件类型,这个东西我在以前也没有发现它的作用,现在看了Ext.Component才明白。且看它的代码:
registerType : function(xtype, cls){
??????????? types[xtype] = cls;
??????????? cls.xtype = xtype;
}
xtype就是新注册的组件类型,它是字符串,而cls不是class哦,它是这个类对应的function,文档上说是这个类对应的构造函数(就是constructor啦)。真相大白了。
  关于Component,我要说的就这么多:一个config,一个组件管理器。

?

  Ext.BoxComponent类

  Ext.BoxComponent继承自Ext.Component,它的主要作用是封装元素的设置位置、宽度的功能。有人说,位置、宽度的设置在Ext.Element不是早就封装了一大把吗?这是个编程技巧,在组件这种高层面上,元素是低层面的,应当尽量把这些内部实现的东西隐藏。不然,不管三七二十一什么事都去访问Ext.Component.getEl()方法,然后为所欲为,那就打破了封装性了。这相当于设计模式中的“外观模式”。功能早就有,只是提供一个高层的接口来访问罢了。

?

  Ext.Container类

  Ext.Container继承自Ext.BoxComponent。对于它,我先介绍一篇分析得不错的文章!点此处进入。

  一句话,这个类是封装布局细节的类,用专业的术语来讲,它是extJs中一堆布局类的外观类,通过它,我们基本上不要去管那些布局细节的事情了,只要在创建组件实例时的config中,加入一个layout:XXXX就成了。如果要对layout初妈化配置,传说中,Ext.Container的config json提供一个叫:layoutConfig的成员。它的详细文档就得看API了。当然,这儿我还是要点一下一些最常用的API。

  config object:width/height/activeItem/defaultType/default/items/layout/layoutConfig/listeners/moniterResize

  常用属性:items/ownerCt

  常用方法:add/insert/remove/findXXXX

  你看,这个使用简单啊。那么是不是所有其他组件都是继承自Ext.Container呢。当然不是,只有像Ext.Panel、Ext.TabPanel、Ext.Window这种复合型的组件才是从Ext.Container继承的。

  到此为止,一定有人对于使用常用组件有些迫不急待了,点此处让大伙来瞧瞧。

?

  好了,大概就是这样了,下面提供一个ExtJs 2.0的组件结构图: