返回深入学习ExtJS 2.2开发系列连载教程目录
浏览的事件是依赖于DOM元素而存在,我们可以把它看作是DOM元素的事件,而Ext中对于事件的扩展主要是为使用Ext元素能使用更方便的事件机制,我们把它称为Ext元素事件,然后在Ext最大的一部分内容是组件,那么它们的事件机制呢?
Ext的组件也是有事件机制的,它是建立在Ext元素的基础之上。像Ext元素事件一样,它也有一个EventObject和对于该对象的管理机制。它们的管理机制也是如何去注册、启动、删除注册的事件。但是它的EventObject却有点不一样,它不是用来保存运行时都产生的信息,而是用来保存为该事件名注册的监听函数。在DOM2事件模型中,就可以为一个事件注册多个监听函数。这些函数要保存在一个地方,并且进行统一的相关的操作,组件的EventObject和这样差不多。
在这一节中,我们就从组件的EventObject和事件机制分别进行讲解。
4.4.1事件对象
组件的EventObject是通过Ext.util.Event类来完成,在DomReady和resize事件中,我们也见过。首先我们知道它是肯定是一个集合,因为它要保存与这个事件名对应着多个监听函数。同时它还要知道它和什么样的事件名相对应。
在Ext.util.Event的构建函数中就是这样去做的:
Ext.util.Event = function(obj, name){
this.name = name;
this.obj = obj;
this.listeners = [];
};
addListener : function(fn, scope, options){
scope = scope || this.obj; 
if(!this.isListening(fn, scope))...{
var l = this.createListener(fn, scope, options);
if(!this.firing)...{ this.listeners.push(l);} 
else...{ this.listeners = this.listeners.slice(0);
this.listeners.push(l); }
}
},
this.listeners = [{fn: fn, scope: scope, options: o,fireFn:h}]
createListener : function(fn, scope, o){ 

o = o || ...{};
scope = scope || this.obj;
var l = ...{fn: fn, scope: scope, options: o};
var h = fn;
if(o.delay)...{ h = createDelayed(h, o, scope); }
if(o.single)...{ h = createSingle(h, this, fn, scope); }
if(o.buffer)...{ h = createBuffered(h, o, scope); }
l.fireFn = h;
return l;
},
fire : function(){
var ls = this.listeners, scope, len = ls.length; 
if(len > 0)...{
this.firing = true;
var args = Array.prototype.slice.call(arguments, 0); 
for(var i = 0; i < len; i++)...{ 
var l = ls[i]; if(l.fireFn.apply(l.scope||this.obj||window,arguments)===false)...{
this.firing = false; return false; }
}
this.firing = false;
}
return true;
}
removeListener : function(fn, scope){
var index; 
if((index = this.findListener(fn, scope)) != -1)...{
if(!this.firing)...{ this.listeners.splice(index, 1); } 
else...{ this.listeners = this.listeners.slice(0);//copy
this.listeners.splice(index, 1); }
return true;
}
return false;
},
addEvents : function(o){ 

if(!this.events)...{ this.events = {};} 
if(typeof o == 'string')...{ 
for(var i = 0, a = arguments, v; v = a[i]; i++)...{
if(!this.events[a[i]])...{ o[a[i]] = true; } }}
else...{Ext.applyIf(this.events, o); }
},
this.addEvents( /** @event disable
* Fires after the component is disabled. 

* @param ...{Ext.Component} this */
'disable',.. ..}
fireEvent : function(){ 
if(this.eventsSuspended !== true)...{ //支持全局的挂起事件
var ce = this.events[arguments[0].toLowerCase()]; 
if(typeof ce == "object")...{
return ce.fire.apply(ce,Array.prototype.slice.call(arguments,1));}①
}
return true;
},|
方法名 |
作用及使用说明 |
|
suspendEvents |
它是用来暂定该组件的事件能力。通过改变代码3.19中this.eventsSuspended属性值为true。 |
|
resumeEvents |
对于暂定事件能力的组件,重新启动它的事件能力,通过改变代码3.19中this.eventsSuspended属性值为false. |
|
relayEvents |
它的格式如下:relayEvents(o,events),它是用来把当前组件中的事件对象逐个地转移注册到o参数指定的对象(组件或元素等)上去。它们对应的关系就是events参数集合中指定的事件名。这就要求o对象和当前组件都有着相关的事件名。在gridPanel中就有应用。 |
表4.8其它方法的说明
被观察者
addListener : function(eventName, fn, scope, o){ 
if(typeof eventName == "object")...{
o = eventName; 
for(var e in o)...{
if(this.filterOptRe.test(e))...{ continue; } ①
if(typeof o[e]=="function")...{this.addListener(e,o[e],o.scope,o);}②
else...{this.addListener(e, o[e].fn, o[e].scope, o[e]);s} ③
}
return;
}
o = (!o || typeof o == "boolean") ? ...{} : o; ④
eventName = eventName.toLowerCase();
var ce = this.events[eventName] || true; 
if(typeof ce == "boolean")...{ ce = new Ext.util.Event(this, eventName);
this.events[eventName] = ce; } ⑤
ce.addListener(fn, scope, o); ⑥
},
listeners: { 
selectionchange: ...{ 
fn: function(dv,nodes)...{
var l = nodes.length;
var s = l != 1 ? 's' : '';
panel.setTitle('Simple DataView ('+l+' item'+s+' selected)');
}
}
}
onSelect : function(record, index){ 
if(this.fireEvent('beforeselect', this, record, index) !== false)...{ ①
this.setValue(record.data[this.valueField || this.displayField]);
this.collapse();
this.fireEvent('select', this, record, index); } ②
},
beforeMethod : function(method, fn, scope){
var e = this.getMethodEvent(method); 

e.before.push(...{fn: fn, scope: scope}); }, 
afterMethod : function(method, fn, scope)...{
var e = this.getMethodEvent(method); 

e.after.push(...{fn: fn, scope: scope}); },
点击展开示例
getMethodEvent : function(method){ 

if(!this.methodEvents)...{ this.methodEvents = {}; } ①
var e = this.methodEvents[method]; 
if(!e)...{
e = ...{};this.methodEvents[method] = e; ②
e.originalFn = this[method]; e.methodName = method;
e.before = []; e.after = [];
var returnValue, v, cancel; var obj = this; 
var makeCall = function(fn, scope, args)...{ ③ 
if((v = fn.apply(scope || obj, args)) !== undefined)...{ 
if(typeof v === 'object')...{ ④
if(v.returnValue!== undefined)...{returnValue = v.returnValue;}
else...{ returnValue = v; }
if(v.cancel === true)...{ cancel = true; }}
else if(v === false)...{ cancel = true; }
else ...{ returnValue = v; } }
} 
this[method] = function()...{ ⑤
returnValue = v = undefined; cancel = false;
var args = Array.prototype.slice.call(arguments, 0); ⑥ 
for(var i = 0, len = e.before.length; i < len; i++)...{
makeCall(e.before[i].fn, e.before[i].scope, args); ⑦
if(cancel)...{ return returnValue; } }
if((v=e.originalFn.apply(obj,args))!==undefined)...{returnValue=v;}⑧ 
for(var i = 0, len = e.after.length; i < len; i++)...{
makeCall(e.after[i].fn, e.after[i].scope, args); ⑨
if(cancel)...{ return returnValue; } }
return returnValue;
};
}
return e;
},
methodEvents={'onselect':{originalFn:onselect,methodName:'onselect',
before:[],ater:[]}}。
methodEvents={'onselect':{originalFn:onselect,methodName:'onselect',
before:[ myFn],ater:[]}}。
defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},
if(!this.el){ var cfg = this.getAutoCreate();
.. ..
this.el = ct.createChild(cfg, position); }
initEvents : function(){
this.el.on(Ext.isIE ? "keydown" : "keypress", this.fireKey, this);
.. ..
},
fireKey : function(e){ 

if(e.isSpecialKey())...{this.fireEvent("specialkey", this, e); }},
var f=new Ext.form.Field(); 

f.on(specialkey:fucntion(t,e)...{//相关处理 });