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

extJs 2.0学习笔记(Element.js篇)

?Element.js这个文件包含了整个extjs框架中最为核心的部分,它对DOM元素进行超强的封装。源文件就有3054行,尽管这中间有好多是注释,但是,在个把月前,我不敢想像我会要拿着几千行的js文件来研究。呵呵。
  就我目前而得知的情报,Ext.Element类至少包含如下功能:

  一、为许多DOM动作创建Animation(动画),例如setWidth,它提供一个可选项来获得动画效果

  二、提供一个伟大的load方法,可以直接ele.load({url:xxxxx}的方式来异步加载数据。超爽、超酷啊。

  其他功能我目前不知,这是看了别人的教程有了这样一个大概的映像。如果要对它获得一个大概映像,点此处访问相关资源!通过这个资源,几乎就可以动手写程序了。

  废话就不多讲了,还是来研究研究源代码。

  一、Ext.Element的缓存机制

Ext.Element = function(element, forceNew){
??? var dom = typeof element == "string" ?
??????????? document.getElementById(element) : element;
??? if(!dom){ // invalid id/element
??????? return null;
??? }
??? var id = dom.id;
??? if(forceNew !== true && id && Ext.Element.cache[id]){ // element object already exists
??????? return Ext.Element.cache[id];
??? }

??? this.dom = dom;

??? this.id = id || Ext.id(dom);
};

  Ext.Element提供了缓存机制,作用:提高性能;原理:让构造过Ext.Element存放在json对象中,如果要再次获得这个对象就不用再次构造,只需从缓存中取出即可。原理很简单。

  上面函数是Ext.Element的构造函数,其中forceNew表示是否强制创建一个新对象,不管缓存中是否已存在。这个构造函数还强制为元素生成id。

  缓存定义在哪?在代码的最后面有一行代码:El.cache = {};可见,缓存是全局的。这是必然。再看看大伙平常用得最多的函数。Ext.Element.get。这个函数都有四十几行的代码,因为整个函数考虑到可能传入参数的类型有好几种的情况,情况多起来,所以有点多。

  二、Ext.fly倒底有什么用?

  Ext.Element有一静态成员fly。它也是获得一个Ext.Flyweight对象的实例。当然,它也是对元素的包装,请见代码:

  var flyFn = function(){};
  flyFn.prototype = El.prototype;
  var _cls = new flyFn();

  // dom is optional
  El.Flyweight = function(dom){
   this.dom = dom;
  };

  El.Flyweight.prototype = _cls;
  El.Flyweight.prototype.isFlyweight = true;

  看清代码了吧?可以说,Flyweight是继承自Element的。不过,正如其名,它是轻量级的。为什么这么说呢?见fly的代码:

El.fly = function(el, named){
??? named = named || '_global';
??? el = Ext.getDom(el);
??? if(!el){
??????? return null;
??? }
??? if(!El._flyweights[named]){
??????? El._flyweights[named] = new El.Flyweight();
??? }
??? El._flyweights[named].dom = el;
??? return El._flyweights[named];
};

  这个代码的关键是,它总是会取得同一个Flyweight对象,用fly取的时候,只要没有传named,所有取的对象都同一个,换的只是dom罢了。

  有人问这有什么好处?好处大了,如果有1000个元素,要调用它们的hide隐藏,如果用Ext.get的话,就会创建1000个Element对象,如果用fly,那只会创建一个对象。这对性能带来巨的提升。所以,在有一些批量式的操作时,用fly要好一些。

  三、对Element.findParent、Element.findParentNode的质疑!!

  原来如此,本来以为它是寻找的对象不包括自己,我总以为没有得到结果,原来,这两个函数是从自己找起的,如果一个元素是div,如果它用findParent找div祖先的话,那找的总是自己。

  这个问题是解决了,不过,我对findParent的代码有疑问,它里面用Ext.getDom(maxDepth)来获得最极限层次的那个节点,事实上,我把getDom传数字的话只会返回数字本身,根本不会返回元素。这个问题我一直想不通。不过,这并不会影响表面上的功能。只是设 maxDepth相当于白设了。

  四、Element的动画支持

  Element要使用动画有三大类方法。

直接调用Ext.Element的animate函数,它建立于Ext.lib.Anim类的基础之上,而Ext.lib.Anim是Adapter里面的类。
在调用Ext.Element的一些设置大小、位置、范围、透时度时,那些函数往往有一个参数,anim,设一设它,也能获得动画效果。
调用从Ext.Fx类中继承过来的方法,如果页面包含了Ext.Fx,那么就可以用所有在Ext.Fx中定义过的函数了。
  一般多用后面两种方法。出人意料的是,Ext.Element继承了Ext.Fx。代码上反应在哪里呢,在Ext.Fx的最后面,有这样一行代码:Ext.apply(Ext.Element.prototype, Ext.Fx);这样一来,在Element中就可放心地使用特效了。关于对Element使用动画,这个现在不是研究重点,这个Ext.Fx要研究的内容。在此一笔带过,实在急于这个问题的,可以点此处阅读相关参考资料!

  五、设置位置、大小、绝对位置、相对位置等等于关定位、范围的函数

  这是个大问题,事实上,前一周我重点就在搞这个问题,例如:

如何取得相对于定位容器的坐标
如可取得相对于页面文档的坐标
如何取得元素的大小,包括边框、内边距、实际内容
如何取得相对于元素的坐标(偏移量)
如何取得视口大小
如何取得当前文档水平滚动、垂直滚动的距离
如何取得当前元素相对于视口左上角的坐标
  问题多吧。这些问题在平常计算时多要用到这些量,然而这些量与浏览器类型严重相关。不同浏览器取法不一样。麻烦、头痛啦。还好,这个问题 Ext.Element都对此进行了封装。不用我们烦心了。当然,上面还仅仅是取得,还有设置这些量的问题,这就至少十五、六个函数了。 Ext.Element又是英文文档,给我们的理解造成了困难呐。下面来把这些东西找出来。到了这里,我再次想起asp.net ajax,这个东西现在与extJs比起来屁都不是啊。在asp.net ajax中,就封装一丁点的东西,它里面的DomElement相当于Element了,只是功能完全不能比,就只有create、addClass、 removeClass、toggleClass,关于我上面提出的七个问题,一个都没有解决。这个框架有跟没有一样。如果有兄弟正在用asp.net ajax,最好还是换一换,换谁都不要用asp.net ajax啊。

  关于这个问题,我一并交到下一文中,下一篇中主要是把Ext.Element中的API归类,比如要创建元素节点并插入某个地方,有哪些方法?