zoukankan      html  css  js  c++  java
  • 读Ext之十四(Ext元素)

    上篇读了Ext.Element的部分方法,这篇继续。El.addMethods方法,

    var ep = El.prototype;
    El.addMethods = function(o){
       Ext.apply(ep, o);
    };
    

    El是Ext.Element类的简写,addMethods可认为是该类的静态方法。无须new使用类名直接调用。其内部调用的是Ext.apply,该方法会将o上的所有属性方法拷贝到ep上。
    使用该方法为Ext.Element类的原型上添加属性,方法。如Ext中队样式的操作、动画、位置等都是通过该方法扩展。
    Ext.apply在 读Ext之一(实用方法) 中介绍了。

    接着看El.get(该类的静态方法),

    El.get = function(el){
        var ex,
            elm,
            id;
        if(!el){ return null; }
        if (typeof el == "string") { // element id
        	// 先使用document.getElementById获取,如果不存在直接返回null
            if (!(elm = DOC.getElementById(el))) {
                return null;
            }
            if (EC[el] && EC[el].el) {
                ex = EC[el].el;
                ex.dom = elm;
            } else {
                ex = El.addToCache(new El(elm));
            }
            return ex;
        } else if (el.tagName) { // dom element
            if(!(id = el.id)){
                id = Ext.id(el);
            }
            if (EC[id] && EC[id].el) {// 先从缓存(Ext.elCache)中取
                ex = EC[id].el;
                ex.dom = el;
            } else {
                ex = El.addToCache(new El(el));// new一个Ext.Element再将其放入缓存中(Ext.elCache)
            }
            return ex;
        } else if (el instanceof El) {
            if(el != docEl){
                el.dom = DOC.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
                                                              // catch case where it hasn't been appended
            }
            return el;
        } else if(el.isComposite) {
            return el;
        } else if(Ext.isArray(el)) {
            return El.select(el);
        } else if(el == DOC) {
            // create a bogus element object representing the document object
            if(!docEl){
                var f = function(){};
                f.prototype = El.prototype;
                docEl = new f();
                docEl.dom = DOC;
            }
            return docEl;
        }
        return null;
    };
    

    该方法是Ext中很重要的方法,用来获取Ext元素(Ext.Element)而不是HTMLElement。想获取对应的HTMLElement,可以这么使用

    Ext.get('id').dom;

    Ext.get是该方法的别名。通常直接使用Ext.get而不是Ext.Element.get。该方法内部实现如下,

    分支1,传id
    先使用document.getElementById获取,如果不存在直接返回null。存在的话,先从缓存(Ext.elCache)中取,否则new一个Ext.Element再将其置入缓存中(Ext.elCache)

    分支2,传HTMLElement对象
    与传id类似,取到id后先从缓存中去,没有则创建Ext.Element再将其置入缓存后返回。


    分支3,传Ext.Element对象
    如果不是docEl(一个临时类),则修改所传参数的dom属性(更新dom)然后返回。

    分支4,传Ext.CompositeElementLite对象
    Ext.CompositeElementLite 在后续会介绍,这个类用来操作批量的Ext.Element。


    分支5,传数组
    使用El.select返回,El.select后续介绍。

    分支6,传document
    如果docEl不存在则创建。因为document是唯一的,因此该对象只创建一次。后续直接返回即可。可以看到docEl与普通Ext.Element不同之处在于其dom属性一个是document,一个则不是。


    分支1中用到了Ext.addToCache,

    El.addToCache = function(el, id){
        id = id || el.id;    
        EC[id] = {
            el:  el,
            data: {},
            events: {}
        };
        return el;
    };
    

    可以看到即把Ext.Element元素以id为key存放到Ext.elCache中。
    存放的改对象有三个属性,el是Ext.Element的实例对象,data用来存储数据(El.data用到),events用来存放事件。

    再往下是El.data方法,该方法是供库内部使用的,它即是setter也是getter。

    El.data = function(el, key, value){
        el = El.get(el);
        if (!el) {
            return null;
        }
        var c = EC[el.id].data;
        if(arguments.length == 2){
            return c[key];
        }else{
            return (c[key] = value);
        }
    };
    

    可以这么测试,

    var p1 = document.getElementById('p1');
    Ext.Element.data(p1,'name','jack'); // setter
    Ext.Element.data(p1,'name'); // getter
    

    经常使用jQuery的人会想到 $.data ,接口于此类似。当然jQuery还有$().data。

    接下来是garbageCollect函数,

    function garbageCollect(){
        if(!Ext.enableGarbageCollector){
            clearInterval(El.collectorThreadId);
        } else {
            var eid,
                el,
                d,
                o;
    
            for(eid in EC){
                o = EC[eid];
                if(o.skipGC){
                    continue;
                }
                el = o.el;
                d = el.dom;
                if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
                    if(Ext.enableListenerCollection){
                        Ext.EventManager.removeAll(d);
                    }
                    delete EC[eid];
                }
            }
            // Cleanup IE Object leaks
            if (Ext.isIE) {
                var t = {};
                for (eid in EC) {
                    t[eid] = EC[eid];
                }
                EC = Ext.elCache = t;
            }
        }
    }
    El.collectorThreadId = setInterval(garbageCollect, 30000);
    

    可以看到,每隔30秒会进行一次垃圾回收。即遍历Ext.elCache。取Ext元素的dom属性,如果存在以下条件则清空(包括其上的所有事件handler)
    1,dom不存在
    2,dom的父元素不存在
    3,页面上获取不到该dom元素

    接下来是Ext.fly,该方法实际上是Ext.Element.fly的别名,客户端程序员多数时候使用Ext.fly而非Ext.Element.fly。

    var flyFn = function(){};
    flyFn.prototype = El.prototype;
    
    El.Flyweight = function(dom){
        this.dom = dom;
    };
    
    El.Flyweight.prototype = new flyFn();
    El.Flyweight.prototype.isFlyweight = true;
    El._flyweights = {};
    
    El.fly = function(el, named){
        var ret = null;
        named = named || '_global';
        if (el = Ext.getDom(el)) {
            (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
            ret = El._flyweights[named];
        }
        return ret;
    };
    

    依次定义了flyFn,El.Flyweight。flyFn的原型是Ext.Element.prototype,El.Flyweight的原型是flyFn的实例对象。
    即El.Flyweight类继承了Ext.Element类原型上的所有属性,方法。

    El.Flyweight.prototype.isFlyweight = true;

    该句通过isFlyweight标示对象是否为Ext.Element.Flyweight类型对象。

    El._flyweights暂存该类型对象,为一个hash。

    El.fly 每次调用都会去创建一个Ext.Element.Flyweight对象,存在El._flyweights后返回。示意图如下:

    注意:El.fly(即Ext.fly)并未将创建的对象缓存,每次调用都将覆盖之前的(除非每次所传的第二个参数named不同)。
    这是Ext.fly不同于Ext.get的地方。这种设计模式称为享元模式(Flyweight),它通过颗粒化将属性分为内部及外部以达到共享从而节省内存。享元模式的实现通常需用到工厂模式。

    再往下是

    Ext.EventManager.on(window, 'unload', function(){
        delete EC;
        delete El._flyweights;
    });
    

    在页面卸载的最后时刻会清空所有的缓存。

    Element.js

  • 相关阅读:
    mybatis-generator自动生成代码时,只生成insert方法
    elasticsearch-head-master下运行npm install报npm WARN elasticsearch-head@0.0.0 license should be a valid SPDX license expression
    fs.default.name和fs.defaultFS
    zookeeper集群为什么要是单数
    Quorom机制
    把数据库放入Docker是一个好主意吗?
    JVM GC算法CMS详解
    JVM之——CMS
    对于TCP/IP协议的三次握手和四次挥手的理解
    JVM G1和CMS
  • 原文地址:https://www.cnblogs.com/snandy/p/2495339.html
Copyright © 2011-2022 走看看