- 浏览: 321547 次
- 性别:
文章分类
最新评论
-
i042416:
分析在哪?
angular分析 -
何盆盆:
你好,请问您这是Extjs3还是Extjs4
ExtJs源码分析与学习—ExtJs事件机制(一) -
124753561:
引用引用引用引用引用[u][u][u][u][i][i][i] ...
Subvision SVN 服务端与客户端的安装 -
谷超:
请问一下例子中itext是什么版本的?
利用iText生成word文档例子参考 -
geosmart:
正好要用到执行字符串中方法,学习了
java中利用反射机制实现调用给定为字符串的方法名
这篇讲ExtJs对事件的管理和调用
ExtJs对事件的管理非常强大,主要定义在Ext.EventManager对象(单例模式)中。先看注册事件监听方式,ExtJs提供了几种方式来注册元素监听函数
- 通过Ext.EventManager.addListener/on函数来为指定元素的某种事件注册监听函数。例如:Ext.EventManager.on('test1','click',clickMe,this);// clickMe是要执行的函数
- 通过ExtJs 元素的on函数来为自身注册某种事件的监听处理函数。例如:
Ext.get('test1').on('click', clickMe,this,{preventDefault:true}); - 通过Ext.addBehaviors函数为多个元素的多个事件注册监听处理函数,该方法在ExtJs源码分析与学习—ExtJs核心代码扩展中已介绍过。
具体来说可分为
标准配置方式
el.on(eventName,fn,scope,options);
options参数是事件配置项,各项说明如下:
scope : 可指定执行上下文
delegate :事件代理
stopEvent :阻止冒泡和默认行为
preventDefault :阻止默认行为
stopPropagation :停止事件冒泡
normalized : 仅传原生事件对象
delay :延迟执行
single : 仅执行一次
buffer :延迟执行,多次时最后一次覆盖前一次
target : 指定在父元素上执行
私有配置多事件注册
el.on({'click':{fn:this.onClick,scope:this,delay:100},
'mouseover':{fn:this.onMouseOver,scope:this},
…
});
共享配置多事件注册
el.on({'click':this. onClick,
'mouseover':this.onMouseOver,
…,
scope:this});
多元素多事件注册
Ext. addBehaviors({
'#foo a@click' : function(e, t){
// do something
},
'#foo a, #bar span.some-class@mouseover' : function(){
// do something
}
);
注意这种共享配置多事件注册监听函数只有两个参数,不能传递配置对象来进行配置,与前三种不同。
上述几种方式最终还是调用Ext.EventManager.addListener函数来注册监听的,该函数源代码如下:
/** * 加入一个事件处理函数,方法{@link #on}是其简写方式。 * @param {String/HTMLElement} element 要分配的html元素或者其id。 * @param {String} eventName 事件处理函数的名称。 * @param {Function} fn 事件处理函数。该函数会送入以下的参数 * @param {Object} scope (optional) (可选的)事件处理函数执行时所在的作用域。处理函数“this”的上下文 * @param {Object} options (optional) (可选的) 包含句柄配置属性的一个对象。该对象可能会下来的属性: * 调用addListener时送入的选项对象。 * <li>scope : Object 事件处理函数执行时所在的作用域。处理函数“this”的上下文环境。 * <li>delegate : String 一个简易选择符,用于过滤目标,或是查找目标的子孙。 * <li>stopEvent : Boolean true表示为阻止事件。即停止传播、阻止默认动作。 * <li>preventDefault : Boolean true表示为阻止默认动作。 * <li>stopPropagation : Boolean true表示为阻止事件传播。 * <li>normalized : Boolean false表示对处理函数送入一个原始、未封装过的浏览器对象而非标准的 * <li>delay : Number 触发事件后处理函数延时执行的时间。 * <li>single : Boolean true代表为下次事件触发加入一个要处理的函数,然后再移除本身。 * <li>buffer : Number 若指定一个毫秒数会把该处理函数安排到{@link Ext.util.DelayedTask}延时之后才执行。 */ addListener : function(element, eventName, fn, scope, options){ if(typeof eventName == 'object'){//事件名为对象,说明采用配置多事件注册 var o = eventName, e, val; for(e in o){ val = o[e]; if(!propRe.test(e)){//非标准模式下不能使用私有自定义的配置项,如options配置了{msg:'提示信息'} if(Ext.isFunction(val)){ // shared options 共享配置项 listen(element, e, o, val, o.scope); }else{ // individual options 私有配置项 listen(element, e, val); } } } } else { listen(element, eventName, options, fn, scope);//标准配置项 } },
该监听函数统一调用了listen,源代码如下:
/** * @param {} element 要注册监听事件的元素 * @param {} ename 事件名 * @param {} opt 配置项 * @param {} fn 监听函数 * @param {} scope 上下文(作用域) * @return {} */ var listen = function(element, ename, opt, fn, scope){ var o = (!opt || typeof opt == "boolean") ? {} : opt;//配置对象 fn = fn || o.fn; scope = scope || o.scope; //监听函数和作用域 var el = Ext.getDom(element);//元素,封装为Ext.Element if(!el){ throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.'; } var h = function(e){//封装之后的监听函数,用来注册到元素的事件中 // prevent errors while unload occurring if(!window[xname]){ return; } e = Ext.EventObject.setEvent(e);//把浏览器原生的事件封装为EventObject对象 var t; if(o.delegate){//如果指定了delegate配置项,那么就按其指定找到代理事件源 t = e.getTarget(o.delegate, el); if(!t){ return; } }else{ t = e.target; } if(o.stopEvent === true){ e.stopEvent(); } if(o.preventDefault === true){ e.preventDefault(); } if(o.stopPropagation === true){ e.stopPropagation(); } if(o.normalized === false){ e = e.browserEvent; } fn.call(scope || el, e, t, o);//调用监听函数,如el.on(eventName,fn,scope,options);则此处调用fn,并传入e, t, o参数 }; if(o.target){ h = createTargeted(h, o); } if(o.delay){ h = createDelayed(h, o); } if(o.single){ h = createSingle(h, el, ename, fn, scope); } if(o.buffer){ h = createBuffered(h, o); } addListener(el, ename, fn, h, scope);//注册为DOM元素的某事件监听函数,及浏览器原生事件 return h; };
在listen函数最后调用了私有函数addListener去注册事件监听函数
/** * There is some jquery work around stuff here that isn't needed in Ext Core. * @param {} el 要注册监听事件的元素,已封装为EventObject * @param {} ename 事件名 * @param {} fn 监听函数 * @param {} task 延迟任务 * @param {} wrap 封装之后的监听函数 * @param {} scope 上下文(作用域) * @return {} */ function addListener(el, ename, fn, task, wrap, scope){ el = Ext.getDom(el); var id = getId(el),// 统一管理事件的id es = Ext.elCache[id].events,//根据元素id找到对应事件监听集合 wfn; wfn = E.on(el, ename, wrap);// 调用Ext.lib.Event.on添加原生的事件,实现浏览器的兼容 es[ename] = es[ename] || []; /* 0 = Original Function, 1 = Event Manager Wrapped Function, 2 = Scope, 3 = Adapter Wrapped Function, 4 = Buffered Task */ es[ename].push([fn, wrap, scope, wfn, task]);//把监听函数保存到监听集合中对应的事件名的集合中 // this is a workaround for jQuery and should somehow be removed from Ext Core in the future // without breaking ExtJS. // workaround for jQuery if(el.addEventListener && ename == "mousewheel"){ var args = ["DOMMouseScroll", wrap, false]; el.addEventListener.apply(el, args); Ext.EventManager.addListener(WINDOW, 'unload', function(){ el.removeEventListener.apply(el, args); }); } // fix stopped mousedowns on the document if(el == DOC && ename == "mousedown"){ Ext.EventManager.stoppedMouseDownEvent.addListener(wrap); } }
以上代码讲解了addListener函数,主要是对原生事件的包装、注册、配置项的处理和事件列表(Ext.elCache[id].events,该列表的初始化定义在Ext.Element.addToCache(new Ext.Element(el), id)方法中,后续会分析)的维护,详细说明请参照代码中的注释。
接下来看删除事件
/** * 移除事件处理器(event handler),跟简写方式{@link #un}是一样的。 * 通常你会更多的使用元素本身{@link Ext.Element#removeListener}的方法。 * Removes an event handler from an element. The shorthand version {@link #un} is equivalent. Typically * you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version. * @param {String/HTMLElement} el 欲移除事件的html元素或id。 The id or html element from which to remove the listener. * @param {String} eventName 事件名称。The name of the event. * @param {Function} fn 事件的执行那个函数。 The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b> * @param {Object} scope 上下文 If a scope (<b><code>this</code></b> reference) was specified when the listener was added, * then this must refer to the same object. */ removeListener : function(el, eventName, fn, scope){ el = Ext.getDom(el); var id = getId(el),//获取el的id,先从缓存中查找 f = el && (Ext.elCache[id].events)[eventName] || [],//值为一数组 wrap, i, l, k, len, fnc; for (i = 0, len = f.length; i < len; i++) { /* 0 = Original Function, 1 = Event Manager Wrapped Function, 2 = Scope, 3 = Adapter Wrapped Function, 4 = Buffered Task */ if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) { if(fnc[4]) { fnc[4].cancel(); } k = fn.tasks && fn.tasks.length; if(k) { while(k--) { fn.tasks[k].cancel(); } delete fn.tasks; } wrap = fnc[1]; E.un(el, eventName, E.extAdapter ? fnc[3] : wrap); // jQuery workaround that should be removed from Ext Core if(wrap && el.addEventListener && eventName == "mousewheel"){ el.removeEventListener("DOMMouseScroll", wrap, false); } // fix stopped mousedowns on the document if(wrap && el == DOC && eventName == "mousedown"){ Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap); } f.splice(i, 1); if (f.length === 0) { delete Ext.elCache[id].events[eventName]; } for (k in Ext.elCache[id].events) { return false; } Ext.elCache[id].events = {}; return false; } } },
代码中方法 removeAll 的功能为移除某个元素所有的事件,而方法 getListeners 的功能为返回元素el对应的事件名eventName所有的监听函数,请看下面的例子
<input type="button" value="点击我" id="btn"> var buttonEl = Ext.get('btn'); buttonEl.on('click',function(e,t,o){alert(e.type + '1');},this); buttonEl.on('click',function(e,t,o){alert(e.type + '2');},this); buttonEl.on('click',function(e,t,o){alert(e.type + '3');},this); var listeners = Ext.EventManager.getListeners(buttonEl,'click'); alert(listeners);
再看方法purgeElement : function(el, recurse, eventName)实现的功能是递归删除元素el以及el的子元素上已注册的事件
参数 el 要删除事件对应的元素
参数 recurse 是否删除el子元素上的事件,true为是
参数 eventName 已注册的事件名,如果没有传入eventName参数,默认则把删除所有的注册的事件
下面看该类中方法onDocumentReady,该方法的简写是Ext.onReady,该方法的功能是当Document准备好的时候触发传入的业务函数。源代码如下
onDocumentReady : function(fn, scope, options){ if (Ext.isReady) { // if it already fired or document.body is present docReadyEvent || (docReadyEvent = new Ext.util.Event());//这样判断是否定义了变量 docReadyEvent.addListener(fn, scope, options);//文档已经载入,传入业务函数,并运行 docReadyEvent.fire(); docReadyEvent.listeners = []; } else {//文档尚未载入,先初始化文档,然后传入业务函数 if (!docReadyEvent) { initDocReady(); } options = options || {}; options.delay = options.delay || 1; docReadyEvent.addListener(fn, scope, options); } },
该方法中当DOM文档没有完全载入时,就通过initDocReady等待,并且把参数中的业务函数注册到docReadyEvent对象中,好让在initDocReady函数注册的fireDocReady函数执行。initDocReady的代码如下
function initDocReady(){ docReadyEvent || (docReadyEvent = new Ext.util.Event()); if (DETECT_NATIVE) {//对于基于 Gecko 、WebKit 和 Safari的浏览器进行等待处理,完全载入运行fireDocReady函数 DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false); } /* * Handle additional (exceptional) detection strategies here * 处理特殊的情况 */ if (Ext.isIE){//IE浏览器完全载入运行fireDocReady,使用readystatechange作为检测标志 //Use readystatechange as a backup AND primary detection mechanism for a FRAME/IFRAME //See if page is already loaded if(!checkReadyState()){ checkReadyState.bindIE = true; DOC.attachEvent('onreadystatechange', checkReadyState); } }else if(Ext.isOpera ){ /* Notes: * Opera需要特殊处理,需要判断css是否加载 Opera needs special treatment needed here because CSS rules are NOT QUITE available after DOMContentLoaded is raised. */ //See if page is already loaded and all styleSheets are in place (DOC.readyState == COMPLETE && checkStyleSheets()) || DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false); }else if (Ext.isWebKit){ //Fallback for older Webkits without DOMCONTENTLOADED support checkReadyState(); } // no matter what, make sure it fires on load // 最无奈的时候,通过load来触发fireDocReady事件 E.on(WINDOW, "load", fireDocReady); }
接下来是两个自运行函数(闭包函数的处理)
initExtCss 初始化Ext Css,用来区分是何种浏览器或操作系统,加载到body上
supportTests 支持测试,怎么用不太明白
以上是对Ext.EventManager代码中主要方法和功能的分析,至此完成了ExtJs对浏览器事件的封装与调用,接下来讲解ExtJs自定义事件的处理,即ExtJs组件事件。
发表评论
-
ExtJs源码分析与学习—Ext.ToolTip应用
2011-12-29 14:18 1841源码待分析,先粘一例子备用 // ... -
ExtJs源码分析与学习—遮罩层
2011-09-06 16:49 4877类Ext.LoadMask ... -
ExtJs源码分析与学习—Ext.UpdateManager
2011-09-06 16:12 2180如果想让html页面中任意元素自动局部刷新,而不是整 ... -
ExtJs源码分析与学习—ExtJs元素Element(六)
2011-06-08 10:41 1795批量操作元素Ext.CompositeElementLite ... -
ExtJs源码分析与学习—ExtJs元素Element(五)
2011-06-07 17:35 1932元素的查询Ext.DomQuery 该 ... -
ExtJs源码分析与学习—ExtJs元素Element(四)
2011-06-07 17:17 3032元素的操作Ext.DomHelper ... -
ExtJs源码分析与学习—ExtJs元素Element(三)
2011-06-07 17:06 1049Ext.Element扩展 通过Ex ... -
ExtJs源码分析与学习—ExtJs元素Element(二)
2011-06-07 16:42 2639元素操作核心类Ext.Elemen ... -
ExtJs源码分析与学习—ExtJs元素Element(一)
2011-06-07 15:47 2128从这一节开始 ... -
ExtJs源码分析与学习—工具类Ext.util.TextMetrics
2011-06-07 15:11 2038Ext提供了一个 ... -
ExtJs源码分析与学习—ExtJs事件机制(六)
2011-06-07 11:25 1481最后把涉及到Ext事件的相关类图贴到这里 ... -
ExtJs源码分析与学习—ExtJs事件机制(五)
2011-06-07 11:15 3056最近一直忙着做产品,所以好久没有写文章了,下面接着 ... -
Ext 组件操作总结——会不断完善
2011-05-10 16:36 26921、Ext.Component 该组件在渲染的时候会默认的 ... -
ExtJs表单几种验证与扩展
2011-05-03 16:26 4897首先说明一下表单验证与其相关的一些设置 Ext ... -
ExtJs源码分析与学习—ExtJs事件机制(四)
2011-03-19 23:37 5306ExtJs组件事件——ExtJs自定义事件的处理 ... -
ExtJs源码分析与学习—ExtJs事件机制(二)
2011-03-15 20:15 2615在ExtJs源码分析与学习—ExtJs事件机制( ... -
ExtJs源码分析与学习—ExtJs事件机制(一)
2011-03-15 18:53 2831前面讲了ExtJs核 ... -
ExtJs源码分析与学习—ExtJs核心代码扩展
2011-01-20 19:16 2083前面三篇文章参考作者snandy总结了Ext中核心 ... -
ExtJs源码分析与学习—ExtJs核心代码(三)
2011-01-17 17:29 2177Ext为javascript的一些对象进行了扩展,主要有Str ... -
ExtJs源码分析与学习—ExtJs核心代码(二)
2011-01-17 16:23 1857接上篇 下面介绍Ext.js ...
相关推荐
在《EXTJS源码分析与开发实例宝典》这本书中,读者可以深入理解EXTJS的内部机制,学习如何利用EXTJS进行高效开发。 标题"EXTJS源码分析与开发实例宝典-开发的效果图.rar"暗示了书中的内容可能包含了EXTJS的源码解析...
《Extjs源码分析与开发实例宝典》全面介绍了ExtJS的技术细节和开发实践,是学习和掌握ExtJS不可或缺的资源。通过对本书的深入阅读,开发者不仅可以理解ExtJS的工作原理,还能学会如何运用ExtJS构建高效、美观的Web...
6. **图表组件**:EXTJS 2.0内置了各种图表类型,如柱状图、饼图、线图等,适用于数据可视化需求,源码分析有助于定制高级图表功能。 7. **Ajax交互**:EXTJS 2.0通过Ajax技术实现与服务器的异步通信,提供了强大的...
**Django整合ExtJS源码解析** 在Web开发领域,Django作为一个强大的Python Web框架,以其高效、安全和可扩展性而备受青睐。与此同时,ExtJS是一个JavaScript库,用于构建富客户端应用程序,提供了丰富的组件和数据...
- **调试工具**:利用浏览器的开发者工具,可以追踪ExtJS源码中的错误和性能瓶颈。 - **主题定制**:ExtJS允许自定义皮肤,通过修改CSS文件,可以调整应用的视觉样式。 6. **与其他技术集成** - **PHP, ASP.NET,...
最后,结合源码分析,提升你的编程水平,能够更好地应对复杂的应用需求。 总之,ExtJs是一个强大的JavaScript框架,通过学习提供的实例和中文教程,结合具体的代码实践,你将能够开发出功能丰富、用户体验优秀的Web...
核心技术部分深入讲解Ext JS的核心基础知识,包括JS原生对象的扩展、事件机制、 模板模型、数据模型,包括一个机制、两个模型及六个扩展。基于元素的开发部分讲解了在DOM元素基 础上扩展的Ext JS元素,包括元素操作...
源码分析: 在`ext-4.0.0`目录中,你将找到ExtJS 4.0的核心源代码。这些文件主要分为以下几个部分: 1. `src`目录:这是ExtJS的核心源码存放处,包含了所有组件、类和工具函数。每个主要的组件或功能都有自己的子...
康海涛的"掏钱学ExtJs完全版"可能是一份全面的学习资料,涵盖了ExtJs的基础到高级应用,包括源码分析,旨在帮助学习者深入理解和掌握这一技术。 首先,ExtJs的核心是其组件模型。它提供了大量的预定义组件,如表格...
通过下载并研究"ext-3.1.0"这个压缩包中的源码和示例,开发者不仅可以学习到ExtJS的基本用法,还能深入理解其内部机制,这对于提升JavaScript开发技能和扩展自定义功能非常有帮助。不过需要注意,随着技术的发展,...
EXTJS的源码学习可以帮助开发者深入理解其内部机制,如数据管理、事件系统、布局管理等。通过分析源码,开发者可以学习到如何自定义组件,优化性能,甚至开发自己的EXTJS插件。此外,熟悉EXTJS的源码也有助于解决在...
这个资料包“ExtJs源码以及文档相关资料”显然包含了ExtJS 4.1.1版本的源代码和相关的文档,这对于深入理解ExtJS的工作原理和学习如何使用它是极为宝贵的资源。 首先,ExtJS 4.1.1是该框架的一个稳定版本,发布于...
- **事件监听**:FileTree中的各种交互行为(如点击、拖放、展开/折叠)都可通过事件监听机制来响应和处理。 深入研究这些源码,可以帮助开发者更好地掌握ExtJs框架的使用,尤其是对文件系统操作的需求。同时,通过...
5. **提醒与通知**:EXTJS支持事件监听和触发,可以实现合同到期、审批超时等重要事件的自动提醒。 在实际部署过程中,`setup.exe`是安装程序,用户可以通过运行这个文件来安装合同管理系统。`安装说明.txt`则提供...
《深入剖析ExtJS_2.2实现及应用》是一本专为高级Web开发者设计的书籍,专注于探讨...它提供的源码分析和实例应用相结合的学习路径,使得读者能在实践中深化理论,在理论中增强实践,从而达到"厚积薄发"的学习效果。
"深入浅出ExtJS随书源码--EXTJS2.0"是针对ExtJS 2.0版本的学习资源,通常与一本相关书籍配套,帮助读者通过实际代码加深对ExtJS的理解。 源码分析: 1. **组件系统**:ExtJS的核心是其组件模型,其中包括各种可...
该随书源码包含三个不同版本的ExtJS源码:ext-3.0.0、ext-3.1.1和ext-3.2.0。这涵盖了ExtJS 3.x的主要迭代,每个版本都可能包含新的特性和改进。通过学习这些源码,读者可以了解到ExtJS的历史演变,以及在不同版本间...
**项目实战源码分析** 这个项目源码中,你将看到以下几个部分: 1. **前端部分**:主要使用ExtJs编写,包括各种页面布局、组件、交互逻辑。你可以在`js`目录下找到相关的JavaScript文件,这些文件定义了ExtJs组件和...
《ASP.NET与EXTJS开发的点卡在线销售系统详解》 在互联网技术高速发展的今天,电子支付和在线交易已经成为日常生活的一部分。点卡作为一种便捷的预付费方式,广泛应用于游戏、软件激活、网络服务等多个领域。本文将...
在"ExtJS5学习之Grid与Grid之间的数据拖拽"这个主题中,我们将深入探讨如何实现这种交互功能,以及背后的机制和重要知识点。 首先,我们要了解ExtJS的Grid组件。Grid是一种可配置的表格视图,它可以显示大量的结构...