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

ExtJs源码分析与学习—ExtJs元素Element(六)

批量操作元素Ext.CompositeElementLite

?

????? 该类提供了对一批元素进行相同操作的实现,他是建立在Ext.Element基础上,类中有一个集合,用来保存一批元素。该类的操作依赖于Ext.select,即Ext.Element.select函数来查询元素。
先看构造器方法

?

Ext.CompositeElementLite = function(els, root){
    this.elements = [];
    this.add(els, root);
    this.el = new Ext.Element.Flyweight();
};

? ? ? 该构造器定义了两个变量,this.elements用来存放要添加的元素,this.el Ext.Element.Flyweight 对象,过程用来处理添加的元素,并利用this.add初始化元素,该方法代码如下:

?

    add : function(els, root){
        var me = this,
            elements = me.elements;
        if(!els){
            return this;
        }
        if(typeof els == "string"){
            els = Ext.Element.selectorFunction(els, root);
        }else if(els.isComposite){
            els = els.elements;
        }else if(!Ext.isIterable(els)){
            els = [els];
        }

        for(var i = 0, len = els.length; i < len; ++i){
            elements.push(me.transformElement(els[i]));
        }
        return me;
    },

?

????? 该函数根据所传不同参数,处理的会不一样,当els为 string时,会调用Ext.Element.selectorFunction返回数组,数组中元素为HTMLElement,Ext.Element.selectorFunction函数是Ext.DomQuery.select的别名,见Ext.DomQuery类的分析;当els.isComposite为true,即els本身就是Ext.CompositeElementLite的实例对象,那么直接取该对象的elements赋值给els;当els不可迭代,即不是数组,也不是对象。如传一个div元素,那么将其包装成数组。该方法中调用了transformElement

?

    transformElement : function(el){
        return Ext.getDom(el);
    },

????? 该方法把el转换为HTMLElement。下面看原型方法prototype

?

   getCount : function(){
        return this.elements.length;
    },

????? 该方法返回集合this.elements的长度。下面看invoke

?

    /**
     * 把Ext.Element.prototype中每一个函数包裹成新的函数,并调用执行
     * @param {} fn
     * @param {} args
     * @return {}
     */
    invoke : function(fn, args){
        var me = this,
            els = me.elements,//元素结合
            len = els.length,
            e,
            i;

        for(i = 0; i < len; i++) {
            e = els[i];
            if(e){//对每个元素都执行Ext.Element类的同名函数
                Ext.Element.prototype[fn].apply(me.getElement(e), args);
            }
        }
        return me;
    },

????? 该函数是为以下函数服务的

?

Ext.CompositeElementLite.importElementMethods = function() {
    var fnName,
        ElProto = Ext.Element.prototype,
        CelProto = Ext.CompositeElementLite.prototype;

    for (fnName in ElProto) {
        if (typeof ElProto[fnName] == 'function'){
            (function(fnName) {
                CelProto[fnName] = CelProto[fnName] || function() {
                    return this.invoke(fnName, arguments);
                };
            }).call(CelProto, fnName);

        }
    }
};

????? 通过下面的调用,把Ext.Element’s prototype复制到Ext.CompositeElementLite’s prototype。

?

Ext.CompositeElementLite.importElementMethods();

?

????? Ext.CompositeElement继承实现了Ext.CompositeElementLite,两者的区别就如同Ext.get和Ext.fly的关系
下面看看Ext.CompositeElement中Ext.Element.select方法

?

Ext.Element.select = function(selector, unique, root){
    var els;
    if(typeof selector == "string"){//css表达式形式
    	//Ext.Element.selectorFunction实际上是Ext.DomQuery.select函数的别名
        els = Ext.Element.selectorFunction(selector, root);
    }else if(selector.length !== undefined){//元素结合的形式
        els = selector;
    }else{
        throw "Invalid selector";
    }
    //构造复合元素,true以Ext.Element形式构件,否则采用Ext.flyweight模式构建
    return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
};

???? Ext.select可以链式调用,如下代码

?

Ext.select('p')
   .addClass('.cls')
   .on('click',function(){alert(this)});

?

下面看个简单的