`
liss
  • 浏览: 829195 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

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

阅读更多

要是以前,我铁定整天到处找教程看,光说不练,现在觉悟了,看教程看得最多,不一定能看完,看完了不一定能比作者更明白,看明白了不一定能用得好。所以看教程其实好处不大,只能作为小小的参考。很多东西看别人的始终是没有用。只有将实验进行到底才是王道……

  这儿主要是代码分析。

 

  研究工具: Dreamweave cs3( 装那个 extJs 2.0 插件老装不上 ) Aptana( 一个好处,好看代码,有括号匹配, json 语法好是好,就是括号多了,搞清在哪儿结束 )

 

  发现, extJs 的代码最喜欢用 json 语法定义,类基本上都是用 json 语法定义的。而不是在外面一大路的 xx.prototype.yyyy=function(){ …… } 。不过这种语法蛮清晰。我喜欢。

 

   extJs 时面只有一个类: Ext ,它是一个静态类。提供了经常要用到的函数。

 

Ext.apply = function(o, c, defaults){

    if(defaults){

        // no "this" reference for friendly out of scope calls

        Ext.apply(o, defaults);

    }

    if(o && c && typeof c == 'object'){

        for(var p in c){

            o[p] = c[p];

        }

    }

    return o;

};

 

  这是 apply 函数,作用其实相当于克隆,它把对象 c 中的成员全部复制到 o 中去。如果有 defaults ,也把它的内容复制到 o 中。这儿其实揭示 javascript 的一种语法:

 

   javascript 中的对象的成员有两种引用方法:

 

  一、 o.propertyName

 

  二、 o[propertyName]

 

  这段代码关键就在 o[p]=c[p] 。这个要理解。尽管如此,但是不能像下面一样做:

 

   var newelem=new Object();

   Ext.apply(newelem,Ext.getDom("a1"));

   Ext.getDom("form1").appendChild(newelem);

 

  下面一大段的代码,由于 dw 不好看代码,半天才晓得那儿是个 (function(){ …… Ext.apply(Ext,{ …… }})() ,这是我把概述出来。这样写呢,实在有点叫人别扭,作者的意图是想把这相关的一段全部放到括号中,以免造成理解上的混乱。能理解。不过,这种写法不大招人喜欢。

 

        applyIf : function(o, c){

            if(o && c){

                for(var p in c){

                    if(typeof o[p] == "undefined"){ o[p] = c[p]; }

                }

            }

            return o;

        }

 

  这是 applyIf 的代码,事实上,在文档上面,它的描述有问题,应当是是当 o,c 两个对象都存在时,则把 o 中不存在, c 中存在的属性复制到 o 中,且属性名不变。而不是所谓“如果 o 不存在时就把属性复制到 o 中”,哪有这种说法的。另外,判断一个对象是不是存在,最严谨的还是用 typeof 的方法。

 

addBehaviors : function(o){

            if(!Ext.isReady){

                Ext.onReady(function(){

                    Ext.addBehaviors(o);

                });

                return;

            }

            var cache = {};

            for(var b in o){

                var parts = b.split('@');

                if(parts[1]){ // for Object prototype breakers

                     var s = parts[0];

                    if(!cache[s]){

                        cache[s] = Ext.select(s);

                    }

                    cache[s].on(parts[1], o[b]);

                }

            }

            cache = null;

        }

 

  这个地方巧妙在于依赖于 Ext.isReady 。这个属性我估计应当是在 onload 第一行将它设成 true 的,它的作用就是用于标志当前是不是已经文档模型加载完了。前面几行的意思:如果 dom 模型还没有加载完,没有准备好,就将这些事件注册代码交给 onload 去做。即 Ext.onReady

 

  如果 DOM 模型已加载完,那么就马上注册事件,区别:前者是延迟注册、后者是马上注册。为什么要延迟,因为 DOM 都没有创建完,有些元素在 DOM 树中还不存在,当然就没法设置它了。其余的地方则不足道,后面的关键就是 Ext.select 了。

 

        id : function(el, prefix){

            prefix = prefix || "ext-gen";

            el = Ext.getDom(el);

            var id = prefix + (++idSeed);

            return el ? (el.id ? el.id : (el.id = id)) : id;

        }

 

  这儿有一个技巧: prefix = prefix || "ext-gen" ,这是最简捷的代码啊。本来要一个 if 语句的。

 

   extend namespace 两个函数硬是没有看懂,等水平高了再来研究。

 

   urlEncode 的源代码原理简单,但是,要是我的话还是没法写得这么清楚,主要是情况比较多。这儿主要是学到了数组的 push ,原来以为 push 只能传一个参数,没想到能一次传多个。发现,很多时候,在构造一个复杂的字符串时都是用到数组的。至于 urlEncode 的作用,就是把一个 JSON 对象编码成一个查询字符串。

 

        each : function(array, fn, scope){

            if(!Ext.isArray(array)){

                array = [array];

            }

            for(var i = 0, len = array.length; i < len; i++){

                if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };

            }

        }

 

  这个函数的功能并不是像它的名字一样简单啊,这儿又学到了:

 

  一、原来构造单元素数组可以直接这样写: a=[a]

 

  二、 scope 在这儿是默认伪调用者,同时,还把当前数组元素值、序号、数组引用都传过去了。这个可能在 fn 中用得着。要注意。

 

  另外就是 x===false 这个语句要注意。要知道 undefined==false

 

        callback : function(cb, scope, args, delay){

            if(typeof cb == "function"){

                if(delay){

                    cb.defer(delay, scope, args || []);

                }else{

                    cb.apply(scope, args || []);

                }

            }

        }

 

  吃了一惊, Function 什么时候有个成员叫 defer 了?后来才知, defer extJs 扩展出来的。 delay 是时延。老实说 scope 这个东西不能言传只可意会,不看代码是不清楚的。事实上 javascript 中的确是存在 defer 属性的。用于修饰 script 元素的,确实是用于延迟 script 里面内容的加载。详情见此处。

 

        destroy : function(){

            for(var i = 0, a = arguments, len = a.length; i < len; i++) {

       var as = a[i];

       if(as){

         if(typeof as.destroy == &apos;function&apos;){

           as.destroy();

       }

       else if(as.dom){

           as.removeAllListeners();

           as.remove();

       }

                }

            }

        }

 

  这个函数用来销毁对象,由代码可知一点, extJs 鼓励大家在创建自己的类有必要的话就写 destroy 。如大量没用的 dom 元素。在这里, destory 相当于析构造函数一样。至于 removeAllListenners remove 这两个函数,它们是 Ext.Element 类的成员。

 

   removeNode : isIE ? function(){

            var d;

            return function(n){

                if(n && n.tagName != &apos;BODY&apos;){

                     d = d || document.createElement(&apos;div&apos;);

                    d.appendChild(n);

                    d.innerHTML = &apos;&apos;;

                }

            }

        }() : function(n){

            if(n && n.parentNode && n.tagName != &apos;BODY&apos;){

                n.parentNode.removeChild(n);

            }

        }

 

  这个代码作用显然,就是删除一个结点。但是这个代码的写法实在有点让人难以接受啊。最郁闷是如果 ie ,那么,那个参数 n 是怎么传进去的呢,因为外面罩住的那个函数没有参数,本来没有参数也好办,关键是外面的那个函数根本没有传参数给 return 里面的函数,这居然也能传进去,见识到了。

 

  经过一番实验与琢磨,发现,其实并不是外面的函数能传参给里面的那个函数,实在是因为那个 () 用得好,如有:

 

   var do1=function(){return function(n){}}();

 

  关键是要外面的函数 {} 之后要马上“自调用”一下,这样就会返回一个结果,这个结果是个函数表达式,它就能传参了。所以如果外面的函数没有 () 的话,那么实际调用将必须写成: do1()(3) 的形式,连写两个括号。。这个问题我想了好久,终于想清楚了。

 

    createCallback : function(/*args...*/){

        // make args available, in function below

        var args = arguments;

        var method = this;

        return function() {

            return method.apply(window, args);

        };

    }

 

  顾名思意,回调。这个函数是对 Function 对象的原型扩展。所以,所有函数都有这个成员。例如:

 

   function A(){}

 

   B=A.createCallback();

 

   B();

 

  最后 B() 执行调用的是 A 。有人说,既然调用 B 就相当于调用 A ,还不如直接用

 

   function B(){A.apply(window,this.argments);}

 

  的确,这样确实可以达到差不多的目的,但是,写代码要注意封装。尽管这只有一行代码,但是,相对于客户程序员来说, createCallback apply 亲切多了,而且,它还节省了不少字符,这就节省带宽。

 

  什么时回调?让别人来调,那为什么不定义在那个调用者里面?因为,只有定义在别人的里面才可以获得别人的信息。

 

  当然,在这儿我还是学到了一点,以前没意识到,怎样把外层的 this 传给内层的 function 。只需 method=this

 

  有一些 Ext 下的函数并没有定义在 ext.js 中。如: Ext.onReady Ext.reg Ext.select Ext.query

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics