- 浏览: 321545 次
- 性别:
文章分类
最新评论
-
i042416:
分析在哪?
angular分析 -
何盆盆:
你好,请问您这是Extjs3还是Extjs4
ExtJs源码分析与学习—ExtJs事件机制(一) -
124753561:
引用引用引用引用引用[u][u][u][u][i][i][i] ...
Subvision SVN 服务端与客户端的安装 -
谷超:
请问一下例子中itext是什么版本的?
利用iText生成word文档例子参考 -
geosmart:
正好要用到执行字符串中方法,学习了
java中利用反射机制实现调用给定为字符串的方法名
元素操作核心类Ext.Element
类Ext.Element对DOM元素的进行了封装,并对DOM加入了简单的操作,实现了各浏览器的兼容;该类的实例可以更容易的对DOM elements进行操作;类中的事件,即封装了浏览器的事件,也可以访问底层浏览器事件(Ext.EventObject{@}#browserEvent);该类操作DOM元素时,很多情况下会用到一些动画效果(可选的),要设置动画效果,一般是把方法中的最后一个参数设为true或配置动画参数,如下代码
var el = Ext.get("my-div"); el.setWidth(100, { duration: 1,//动画持续的时间(单位:秒) callback: function(){alert('动画结束');}, scope: this }); <div id='my-div'> 动画效果 </div>
该类的实现同样也采用了匿名闭包自执行函数来实现,执行的结果把函数赋给了Ext.Element,同时扩展了Ext.Element的prototype。首先看Ext.Element的定义
Ext.Element = function(element, forceNew){ var dom = typeof element == "string" ? DOC.getElementById(element) : element, id; if(!dom) return null; id = dom.id; if(!forceNew && id && Ext.elCache[id]){ // element object already exists return Ext.elCache[id].el; } /** * The DOM element * @type HTMLElement */ this.dom = dom; /** * The DOM element ID * @type String */ this.id = id || Ext.id(dom); };
该类的实现采用了构造器方法,两个参数分别为
element:要封转的DOM元素或id,通常为HTMLElement
forceNew:(可选的) 构建函数默认会检查在Cache中是否已经有这个element实例。如果有,则返回缓存中的对象。如果设置为否,则跳过缓存的验查。
该构造器中初始了元素id(如果没有设置则调用Ext.id(dom))和dom,注意如果forceNew 没有传入或设为false先从缓存中找,找到返回该元素封装后的Element
return Ext.elCache[id].el;
我们知道这是在定义一个类,使用new操作符。如
var ele = new Ext.Element('head');
既然是new,里面怎么又return了呢?一般函数调用,有return时,构造器中都会定义一些字段。其实当构造器中return的是对象类型时是允许的,如果return的是基本类型,又使用new调用函数则会出现非预期的效果。对于这点说明详见:具名函数的四种调用方式 系列
。
利用构造器定义完该类后,代码定义了一些变量
var DH = Ext.DomHelper, El = Ext.Element, EC = Ext.elCache;
Ext采用这种简单的设计模式:组合。Bruce Eckel在《Think in Java》中所言,避免滥用继承,多数情况下组合已足以。下面看原型prototype的实现
set : function(o, useSet){ var el = this.dom, attr, val, useSet = (useSet !== false) && !!el.setAttribute; for (attr in o) { if (o.hasOwnProperty(attr)) { val = o[attr]; if (attr == 'style') { DH.applyStyles(el, val); } else if (attr == 'cls') { el.className = val; } else if (useSet) { el.setAttribute(attr, val); } else { el[attr] = val; } } } return this; },
该方法设置元素属性(attributes)(一个样式属性可以是字符串,对象或函数function)。传入的属性会优先设置style,其次是cls,然后是setAttribute,最后为直接设置元素属性,如table.width = '10px; '。其中参数useSet (optional) false表示用元素的setAttribute方法来设置属性值,关于setAttribute的使用以及不同浏览器的不兼容型,该文章
给出了详细的说明。
该方法内部使用for in来遍历对象,我们知道默认情况下 for in 不会去遍历原形链属性的
。
对象的hasOwnProperty方法对继承于原形链的属性是检测不到
的,即返回false。因此这里hasOwnProperty(attr) 这个判断完全是多余的。
在设置style调用了DH.applyStyles(el, val);该方法后续会讲到。
接下来看代码
defaultUnit : "px",
CSS值的单位。如不指定则默认为px。
is : function(simpleSelector){ return Ext.DomQuery.is(this.dom, simpleSelector); },
该方法功能为:如果这个元素符合传入的简易选择符的条件就返回true,简易选择符形如div.some-class或span:first-child。实现详见Ext.DomQuery
focus : function(defer, /* private */ dom) { var me = this, dom = dom || me.dom; try{ if(Number(defer)){ me.focus.defer(defer, null, [null, dom]); }else{ dom.focus(); } }catch(e){} return me; },
方法focus使这个元素得到焦点。defer (optional)为延时执行focus的毫秒数。该方法忽略了任何已捕获的异常。与focus对应的方法为blur
blur : function() { try{ this.dom.blur(); }catch(e){} return this; },
下面看方法getValue
getValue : function(asNumber){ var val = this.dom.value; return asNumber ? parseInt(val, 10) : val; },
返回元素的value属性值,如果asNumber为true,则转换为十进制数字
下面的几个方法是与事件相关的,主要调用Ext.EventManager来实现的,这里说明一下,通过这几个方法的定义,该类实现了元素对浏览器所有事件的支持。
addListener / removeListener / removeAllListeners / purgeAllListeners
下面看方法load
load : function(url, params, cb){ Ext.Ajax.request(Ext.apply({ params: params, url: url.url || url, callback: cb, el: this.dom, indicatorText: url.indicatorText || '' }, Ext.isObject(url) ? url : {})); return this; },
运行该方法时,会调用请求,用返回的值赋给元素的innerHTML,该方法的实现参见Ext.Ajax.request
isBorderBox : function(){ return Ext.isBorderBox || Ext.isForcedBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()]; },
该方法测试不同的CSS规则/浏览器以确定该元素是否使用Border Box。IE并且是标准模式则返回Ext.isBorderBox,如果是非IE并且强制设置border-box model则返回1,否则标准模式中对于具有border的元素如select会返回1,怪异模式中对于input,select,textarea元素返回1,同时利用代码noBoxAdjust['button'] = 1,button也会返回1。
remove : function(){ var me = this, dom = me.dom; if (dom) { delete me.dom; Ext.removeNode(dom); } },
从DOM里面移除当前元素,并删除缓存以及该element注册的事件(参见Ext.removeNode)。
看以下代码
hover : function(overFn, outFn, scope, options){ var me = this; me.on('mouseenter', overFn, scope || me.dom, options); me.on('mouseleave', outFn, scope || me.dom, options); return me; },
该方法设置元素事件句柄,当鼠标进入和离开该元素时调用传入的事件函数,方法中调用me.on,前面已讲过该方法的使用。方法中用mouseenter和mouseleave,而没有用mouseover和mouseout,好处前面已提到,ExtJs已经扩展实现了这两个事件不同浏览器之间的兼容。
contains : function(el){ return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el); },
该方法用来判断当前元素是否是传入元素的父辈级元素(ancestor),是返回true。
下面看代码
getAttributeNS : function(ns, name){ return this.getAttribute(name, ns); }, getAttribute : Ext.isIE ? function(name, ns){ var d = this.dom, type = typeof d[ns + ":" + name]; if(['undefined', 'unknown'].indexOf(type) == -1){ return d[ns + ":" + name]; } return d[name]; } : function(name, ns){ var d = this.dom; return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name]; },
这两个方法功能为返回DOM节点中的某个元素属性的值。当有命名空间时,应传入ns参数,注意IE和非IE的实现不一样。IE中对undefined,unknow类型做了处理,其它浏览器则是标准的实现。关于该方法带命名空间的使用下面给出一个简单的例子
<div id='attDemo' ext:url='自定义属性测试结果' style="width :200px;">带命名空间的自定义属性</div> var attDemo = Ext.get('attDemo'); var att = attDemo.getAttribute('url','ext'); alert(att);
最后看方法
update : function(html) { if (this.dom) { this.dom.innerHTML = html; } return this; }
更新该元素的innerHTML
下面看Ext.Element的静态方法
var ep = El.prototype; El.addMethods = function(o){ Ext.apply(ep, o); };
该方法内部调用Ext.apply,把o中的所有属性克隆到ep上
下面看重要方法get
El.get = function(el){ var ex, elm, id; if(!el){ return null; } if (typeof el == "string") { // element id 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) { ex = EC[id].el; ex.dom = el; } else { ex = El.addToCache(new El(el)); } return ex; } else if (el instanceof El) { if(el != docEl){ // refresh dom element in case no longer valid, // catch case where it hasn't been appended // If an el instance is passed, don't pass to getElementById without some kind of id if (Ext.isIE && (el.id == undefined || el.id == '')) { el.dom = el.dom; } else { el.dom = DOC.getElementById(el.id) || el.dom; } } 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; };
该方法是一静态方法,他的功能是获取元素对象。get方法不会获取组件对象Ext.Component Component,而只是对DOM元素进行Ext.Element封装,要想获取组件,请调用方法Ext.ComponentMgr.get。Ext.get是该方法的别名。对于传入的参数el可分为以下几种情况
1、传入参数是dom的id:首先利用DOC.getElementById(el)判断该dom是否存在,存在的话先从缓存中取,不存在的话实例化该对象并压入到缓存中
2、传入参数是HTMLElement对象:首先判断该dom是否有id值(没有则创建),对于该种情况也是先从缓存中取,与1一样
3、传入参数是Ext.Element,即已经封装好的对象:如果不是docEl,重新给dom属性赋值后直接返回
4、传入参数是Ext.CompositeElementLite:直接返回
Ext.CompositeElementLite 在后续会介绍,这个类用来操作批量的Ext.Element
5、传入参数是数组的话:调用El.select(el)返回,后续会介绍
6、传入参数是document:
如果docEl不存在则创建。因为document是唯一的,因此该对象只创建一次。后续直接返回即可。可以看到docEl与普通Ext.Element不同之处在于其dom属性的不同。
这几种情况如果传入的元素不存在则返回null。该方法调用了以下方法
El.addToCache = function(el, id){ id = id || el.id; EC[id] = { el: el, data: {}, events: {} }; return el; };
该方法,会在Ext缓存中以id为key存放到Ext.elCache中,存放的对象有三个属性,分别为Ext.Element,存储数据(El.data用到)、Ext封装的事件(见Ext.EventManager方法addListener),events保存了以事件名为属性的事件信息,包括调用函数,作用域等。
接下来是一个垃圾回收函数
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)
- dom不存在
- dom的父元素不存在
- 页面上获取不到该dom元素
用户也可以取消垃圾回收,只要把参数Ext.enableGarbageCollector设为false即可。该方法的思想也可以用到其他函数或类中
接下来是Ext.Element.fly方法,他的别名是El.fly
var flyFn = function(){}; flyFn.prototype = El.prototype; // dom is optional 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; };
首先利用javascript的简单继承定义flyFn,该类继承Ext.Element,然后添加El.Flyweight类,同时该类的原型是flyFn的实例对象,并增加了属性isFlyweight,来标示对象是否为Ext.Element.Flyweight类型对象。而El._flyweights为暂时对象。每次调用Ext.fly(El.fly)方法时,都会把El.Flyweight对象缓存到El._flyweights的nameed中,并且将覆盖之前的(除非每次所传的第二个参数named不同),而El.Flyweight中dom保存了当前元素的dom。
Ext.fly不同于Ext.get。Ext.fly采用享元模式(Flyweight),它通过颗粒化将属性分为内部及外部以达到共享从而节省内存。享元模式的实现通常需用到工厂模式。
发表评论
-
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 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:20 3254这篇讲ExtJs对事件的管理和调用 Ext ... -
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 ...
相关推荐
作者采用了"core→element→component"的主线,将整个ExtJS源码结构串联起来,确保读者能逐步深入学习,理解每一层的细节。 "Introduction"章节为初学者提供了入门指导,涵盖了ExtJS的基本概念和安装步骤。"Core...
本书还深入探讨了JavaScript技术,特别是针对ExtJS源码分析所需的JS知识点。虽然不完全是针对JavaScript初学者,但对于进阶开发者,它提供了许多其他书籍中未涉及的内容,如正则表达式的解析原理和高效正则编写,...
- **源码细节**:发布ExtJS源码时会涉及到一些具体的细节问题,如文件结构、依赖关系等。 - **从何入手**:对于初学者来说,可以从简单的示例开始,逐步深入到更复杂的组件和功能。 #### 9. 适配器Adapters与核心...
**二、源码分析** 书中对ExtJS 3.0的源码进行了深入解析,帮助读者理解其内部工作原理。这包括: 1. **核心类库**:讲解了Ext的基础类,如Element、Component、Store、Grid等,这些是构建所有组件的基础。 2. **...
在EXTJS7中,开发人员有时需要允许...通过以上分析,我们可以了解到EXTJS7中实现点击拖拉选择文本的机制,以及如何在组件级别和子元素级别进行配置。开发者可以根据实际需求灵活地调整这些配置,以提供更好的用户体验。
在IT行业中,JavaScript库ExtJS是一个广泛使用的前端框架,它为构建复杂的...因此,深入学习"读Ext之十五(操作批量元素)"这篇博客,并结合`CompositeElementLite.js`的源码分析,将是提升ExtJS开发能力的关键步骤。
EXTJS 3.0.0源码的分析可以帮助我们深入理解其工作原理,从而更好地利用这个框架来开发复杂的Web应用。 EXTJS的核心是组件模型,它包括各种可复用的UI组件,如表格、面板、表单、树形视图、菜单等。在EXT 3.0.0中,...
书中的内容结构严谨,以"core"(核心)、"element"(元素)和"component"(组件)这三个关键词为主线,串联起EXTJS的整个源码体系。同时,通过一个网络办公系统的实例,将各个知识点贯穿起来,使读者能够逐步学习并...
- **Element对象**:Ext的核心概念之一,用于操作DOM元素,提供了丰富的API来进行DOM操作,如获取、设置样式、位置等。 - **获取多个DOM的节点**:可以通过CSS选择器获取多个DOM节点,并进行批量操作。 - **响应...
手册通常包括EXT的基本概念、安装和下载步骤、组件的使用方法、事件处理、Ajax通信、源码分析等多个章节。其中,"EXT简介"部分会介绍EXT的基本理念和架构;"下载EXT"则会指导开发者如何获取EXT库并将其引入项目;...
源码分析可以帮助开发者更好地掌握框架的工作原理,从而更有效地进行调试和优化。源码概述章节通常会介绍EXT的架构设计、关键模块的功能及其实现方式,以及在发布源码时需要注意的细节,如依赖管理、代码结构和最佳...
源码分析涉及组件架构、事件处理流程、数据绑定机制等方面,对于定制高级功能和调试问题尤为重要。 **九、程序规划入门** 在使用EXT JS进行项目开发前,合理的规划至关重要。这包括选择合适的布局、定义组件层次、...
- **源码分析**:深入分析EXT的源码结构,帮助开发者理解其内部机制。 - **细节讲解**:特别关注了在发布EXT源码过程中需要注意的细节问题,如兼容性考虑、性能优化等。 #### 10. EXT程序规划入门 - **准备工作**:...
- **案例分析**:通过具体的案例分析,帮助开发者深入理解 Ext 的使用方法。 综上所述,《EXT 中文手册》涵盖了 Ext 框架的基础知识、核心概念、高级功能以及实际应用案例,对于想要掌握 Ext 开发的读者来说是一份...