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

Extjs源码之--Ext事件机制/继承关系

Extjs源码之--Ext.lib.Event 中分析了EXT事件简单封装,其实EXT事件主要有三个对象组成,而这些对象是相互继承或者是说结构上的从下到上的依赖关系,Ext.lib.Event是基础,封装了基本的事件模型,他是这个事件体系中的核心和基础,是属于adapter级别的,他屏蔽了浏览器的特征,这个对象其实是不对外的,从Ext源码中你也能发现这么一段(This function should ALWAYS be called from Ext.EventManager),这是对事件的监听的,其他的就封装在Ext.EventObject中。接下来是 Ext.EventObject 对象


看下面这段代码,这是Ext.EventObject构造函数

var E = Ext.lib.Event;
Ext.EventObjectImpl = function(e){
        if(e){
            this.setEvent(e.browserEvent || e);//注意这里
        }
    }

在看 setEvent 函数都做了些什么
Ext.EventObjectImpl.prototype = {
           /** @private */
        setEvent : function(e){
            var me = this;
            if(e == me || (e && e.browserEvent)){ // already wrapped
                return e;
            }
            me.browserEvent = e;
            if(e){
                // normalize buttons
                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
                if(e.type == 'click' && me.button == -1){
                    me.button = 0;
                }
                me.type = e.type;
                me.shiftKey = e.shiftKey;
                // mac metaKey behaves like ctrlKey
                me.ctrlKey = e.ctrlKey || e.metaKey || false;
                me.altKey = e.altKey;
                // in getKey these will be normalized for the mac
                me.keyCode = e.keyCode;
                me.charCode = e.charCode;
                // cache the target for the delayed and or buffered events
                me.target = E.getTarget(e);
                // same for XY
                me.xy = E.getXY(e);
            }else{
                me.button = -1;
                me.shiftKey = false;
                me.ctrlKey = false;
                me.altKey = false;
                me.keyCode = 0;
                me.charCode = 0;
                me.target = null;
                me.xy = [0, 0];
            }
            return me;
        }
}

从上面代码很清楚的看到,Ext.EventObject构造函数除了对存在的兼容性问题进行屏蔽,还把 Ext.lib.Event属性传给了新的对象,如:me.target = E.getTarget(e);,me.xy = E.getXY(e);。接下来就是一些对外的接口方法,所以这个对象是提供对外接口的

Ext.EventObject = function(){
    var E = Ext.lib.Event,
        // safari keypress events for special keys return bad keycodes
        safariKeys = {
           
        },
        // normalize button clicks
        btnMap = Ext.isIE ? {1:0,4:1,2:2} :
                (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});

    Ext.EventObjectImpl = function(e){
        if(e){
            this.setEvent(e.browserEvent || e);
        }
    };
     Ext.EventObjectImpl.prototype = {
           /** @private */
        setEvent : function(e){
        
        },
        。。。。。。。。
     }
     return new Ext.EventObjectImpl();
}

再来看看Ext.EventManager 对象的结构:
Ext.EventManager = function(){
  var .......//一堆变量/常量的定义
   E = Ext.lib.Event,//这俩个变量要注意
   D = Ext.lib.Dom,//
   ..............////一堆变量/常量的定义
  
   //接下来一堆的 function 
   ......................

   //接下来是返回对象,也就是这个对象为外部提供接口
   var pub = {
           addListener : function(element, eventName, fn, scope, options){},
           removeListener : function(el, eventName, fn, scope){},
           removeAll : function(el){},
           getListeners : function(el, eventName) {},
           purgeElement : function(el, recurse, eventName) {},
           _unload : function() {},
           onDocumentReady : function(fn, scope, options){}
    };
    
    pub.stoppedMouseDownEvent = new Ext.util.Event();
    return pub;
}


从上面提供的接口看,Ext.EventManager实际上还是对 Ext.lib.Event的扩展和封装,以提供统一的对外接口,而且这里还提供了onDocumentReady这个接口,这个接口涉及到浏览器兼容性问题!而且这个接口的很多函数都用到了Ext.EventObject对象中的方法,所以从代码上看Ext.EventManager是依赖于Ext.EventObject的扩展的!理解了