`

Ext.get()与Ext.fly()之区别

    博客分类:
  • Ext
 
阅读更多

从一开始接触Ext就看到有Ext.fly这个函数,当时觉得这个跟Ext.get没什么区别,加之当时对JS性能相关问题认识肤浅,也一直没有在意其区别,今日看learning extjs一书,看到了有专门对Ext.fly特别强调的一处:

This isn't exactly a speed tip, but is more about conserving memory by using
something called a "flyweight" to perform simple tasks, which results in higher speed
by not clogging up the browser's memory

大概意思也就是Ext.Fly采用flyweight模式使所有fly出来的元素共享内存,可以提高程序执行速度,减少内存占用。

这段话激起了我对这个函数的兴趣,毕竟近段时间一直在搞JS性能优化相关问题,对“内存”这个字眼非常敏感。大概看了下Ext源码对get和fly实现的部分,然后在网上查看了一些资料,终于对他们之间的异同有了个比较深入的认识。
Ext的官方开发人员给出了如下的解释:

Ext.Element wraps a lot of functionality around DOM element/node, for example functions like hide, show, all animation stuff, dimensions getting and setting function and a lot more.

Ext.Element keeps reference to DOM element it is wrapped around in dom property. Once you have an Ext.Element (e.g. you call Ext.get('some-id') it is an instance of Element class and you can work with it as such.

Now, imagine that you need to hide 1000 DOM nodes, you call 1000 times Ext.get('some-one-of-1000-id').hide() so you create 1000 instances of Element just to call one function: hide.

Ext.fly is one instance of Ext.Element with "replaceable" DOM node it is wrapped around. If you call 1000 times Ext.fly('some-one-of-1000-id').hide() you 1000 times replace dom property of one instance of Ext.Element.

Result: higher performance, lower memory usage.

You only need to keep in mind that you cannot keep Element returned by Ext.fly for later use as it's dom will sooner or later gets replaced by another one.

这段话中,大致的意思如下:

Ext.Element是Ext对Dom元素的一个强有力封装,它封装了很多方便对dom操作的接口(并通过Element的dom属性引用对应的 dom元素),因此每创建一个Element元素都将消耗不少的内存(主要是大量的操作接口消耗),因此如果创建过多的Element元素必然导致内存占 用的剧增和系统性能的下降。

Ext.get和Ext.fly返回的都是一个Element对象,但是Ext.get返回的是一个独立的Element,拥有自己独立的操作接口 封装,可以将其返回值保存到变量中,以便以后调用操作等,这样为重用带来了方便。但是它的一个很大缺点就是内存消耗问题,假如调用 Ext.get(id)1000次,则会在内存中创建1000个独立Element,其内存占用可想而知。但是很多时候我们可能仅仅只是对该dom元素执 行一次很简单的操作,如隐藏(hide),这样如果每次都创建一个独立Element放在内存中,实在是对内存的巨大浪费,因此当我们在只需要执行一次操 作或者一个很简单的操作时,采用Ext.get就显得很不合理。Ext.fly正是为了解决这个问题而出现,它通过使每次创建的Element共享内存中 的一套操作接口来达到节省内存的效果。

下面来看Ext.fly的实现代码(我简单加了一些注释):

var

 flyFn = function

(){}; 
flyFn.prototype

 = El.prototype

; 
var

 _cls = new

 flyFn(); //将Element的所有操作接口放在_cls中

 

// dom is optional

 
El.Flyweight = function

(dom){ 
this

.dom = dom; 
}; //仅包含一个dom属性的Object

 

El.Flyweight.prototype

 = _cls; //将操作接口复制给Element实例对象

 
El.Flyweight.prototype

.isFlyweight = true

; //标志该Element是flyweight对象

 

El._flyweights = {}; //flyweight对象缓存容器

 

El.fly = function

(el, named){ 
 named = named || '_global'

; 
 el = Ext.getDom(el); //取得dom对象

 
if

(!el){ 
return

 null

; 
 } 
if

(!El._flyweights[named]){ 
 El._flyweights[named] = new

 El.Flyweight(); //仅在第一次调用Ext.fly时创建一个Flyweight对象并缓存

 
 } 
 El._flyweights[named].dom = el; //将flyweight对象的dom属性指向该el

 
return

 El._flyweights[named]; 
};

var flyFn = function(){};<br/>flyFn.prototype = El.prototype;<br/>var _cls = new flyFn(); //将Element的所有操作接口放在_cls中<br/><br/>// dom is optional<br/>El.Flyweight = function(dom){<br/> this.dom = dom;<br/>}; //仅包含一个dom属性的Object<br/><br/>El.Flyweight.prototype = _cls; //将操作接口复制给Element实例对象<br/>El.Flyweight.prototype.isFlyweight = true; //标志该Element是flyweight对象<br/><br/>El._flyweights = {}; //flyweight对象缓存容器<br/><br/>El.fly = function(el, named){<br/> named = named || '_global';<br/> el = Ext.getDom(el); //取得dom对象<br/> if(!el){<br/> return null;<br/> }<br/> if(!El._flyweights[named]){<br/> El._flyweights[named] = new El.Flyweight(); //仅在第一次调用Ext.fly时创建一个Flyweight对象并缓存<br/> }<br/> El._flyweights[named].dom = el; //将flyweight对象的dom属性指向该el<br/> return El._flyweights[named];<br/>};

从上面的代码不难看出,仅在第一次调用Ext.fly时创建一个Flyweight对象(该对象包含了Element的所有操作接口)并将其缓存, 之后的所有fly操作都只是修改该flyweight对象的dom属性,每次fly返回的结果都是共享的同一个flyweight对象。这样每次fly返 回的Element相比Ext.get而言,减少了每次创建Element时对大量的操作接口的创建。所有fly的对象都共享一套Element操作接 口,内存占用自然少了很多,而且执行速度也得到了提升。在大量的创建操作中效果会更加明显。

由于fly的操作原理,我们不能将fly的返回结果保存在变量中以便重用,因为每次fly操作都将可能改变该变量的dom指向。如下面的代码就是不正确的:

var

 my_id = Ext.fly('my_id'

); 
 Ext.fly('another_id'

); //此时my_id的dom引用已经变为another_id

 
 my_id.highlight('FF0000'

,{ //此处的操作将是对another_id元素的操作

 
 endColor:'0000FF'

, duration: 3

 
 });

var my_id = Ext.fly('my_id');<br/> Ext.fly('another_id'); //此时my_id的dom引用已经变为another_id<br/> my_id.highlight('FF0000',{ //此处的操作将是对another_id元素的操作<br/> endColor:'0000FF', duration: 3<br/> });

在以后使用中,一定要合理的利用Ext.get和Ext.fly,避免滥用Ext.get这个“重量级”的方法。

分享到:
评论

相关推荐

    Ext.get与Ext.fly的区别

    ### Ext.get与Ext.fly的区别 在Ext JS框架中,`Ext.get`和`Ext.fly`是两个非常重要的方法,它们主要用于操作DOM元素。理解这两个方法之间的区别以及如何使用它们对于开发高质量、高效率的应用程序至关重要。 #### ...

    Ext.get与Ext.fly 的区别

    在EXTJS这个强大的JavaScript框架中,`Ext.get`和`Ext.fly`是两个非常重要的方法,它们都用于操作DOM元素,但它们之间存在着微妙的差异。了解这些差异对于优化代码性能和理解EXTJS的工作机制至关重要。 首先,`Ext....

    3------通过实例学习------Ext.js------.pdf

    `Ext.fly`是另一个与`Ext.get`相似但略有不同的方法,它主要用于一次性操作DOM元素,可以减少内存消耗,适用于只需要执行一次操作的情况。 学习Ext.js不仅是学习其API和组件,更重要的是理解其背后的MVC(Model-...

    3------通过实例学习------Ext.js------.docx

    `Ext.fly`函数类似,但它的设计目的是快速执行一次性的DOM操作,而不需要保留对元素的引用,适合一次性操作的场景。 在Ext.js中,DOM操作是非常重要的部分。`Ext.get`和`Ext.getBody`是两个常用的DOM访问方法,前者...

    Ext Js权威指南(.zip.001

    6.5.2 ext.dom.compositeelement与ext.dom.compositeelementlite的区别 / 279 6.5.3 操作元素集合 / 279 6.6 综合实例:可折叠的面板accordion / 280 6.7 本章小结 / 283 第7章 数据交互 / 284 7.1 数据交互...

    EXTJS总结.txt

    1.Ext.get var el = Ext.get('myElementId');//获取元素,等同于document.getElementById('myElementId');//会缓存 2. Ext.fly var el = Ext.fly('myElementId')//不需要缓存。 注:享元模式(Flyweight Design ...

    ext初级入门

    例如,`Ext.getDom('elId')`用于通过ID查找DOM节点,而`Ext.getDom(elDom)`则用于通过现有DOM节点查找DOM节点。 接下来,我们讨论EXT中的一些CSS元素操作: 4. **addClass**:使用`Ext.fly('elId').addClass('...

    extjs 学习笔记(二) Ext.Element类

    本篇学习笔记将深入探讨`Ext.Element`类,包括`Ext.fly`和`Ext.get`的区别以及如何使用`Ext.Element`进行各种DOM操作。 首先,`Ext.fly` 和 `Ext.get` 都是用来获取`Ext.Element`对象的方法,但它们之间存在一些...

    EXT核心API详解(第一部分)

    `Ext.get`和`Ext.fly`方法用于获取Element实例,`Ext.query`则类似于jQuery的`$`,用于选取DOM元素。Element对象还支持事件监听和动画效果。 3. **基本数据类型扩展**:EXT JS扩展了JavaScript的基本数据类型,如...

    ExtJS对Ajax的支持

    **Ext.Ajax**是ExtJS框架中的一个核心组件,用于实现与服务器的异步通信,即Ajax请求。这一功能对于构建动态、响应式和交互式的Web应用至关重要。Ext.Ajax提供了一套封装良好的API,使得开发者能够更轻松地管理HTTP...

    extjs核心api详解

    文章最后提到了Ext类的一些常用方法,如addBehaviors、apply、applyIf、decode、destroy、each、encode、escapeRe、extend、fly、get、getBody、getCmp等。这些方法提供了丰富的功能,如事件绑定、对象拷贝、JSON...

    Ext Core手册 繁体体中文pdf版.7z

    例如,`Ext.get()`方法用于获取DOM元素,`Ext.fly()`则允许快速访问并执行一次操作,而无需创建DOM选择器对象。此外,还有用于添加和删除类名、设置样式属性以及处理事件的方法。 **三、事件处理** Ext Core 提供了...

    Ext4.2的Ext.grid.plugin.RowExpander无法触发事件解决办法

    row = Ext.fly(rowNode, '_rowExpander'), nextBd = row.down(me.rowBodyTrSelector, true), isCollapsed = row.hasCls(me.rowCollapsedCls), addOrRemoveCls = isCollapsed ? 'removeCls' : 'addCls', ...

    EXT核心API详解

    var el = Ext.fly('some-element', 'named'); // 获取带有ID "some-element" 的浮动元素 ``` ##### 11. `get(Mixed el):Element` - **功能**:获取一个Element对象。 - **参数**: - `el`:可以是ID、DOM节点或...

    EXT核心API详解.doc

    例如,`Ext.getBody()`可以获取当前文档的body对象,`Ext.getDom()`则可以由ID或DOM节点获取对应的DOM元素。 2. **addBehaviors**: 这个方法用于批量添加事件监听器。它允许你使用一种简洁的方式来为多个选择器绑定...

    Ext js2.1 最新资料汇总

    ### Ext JS 2.1 核心 API 详解 #### 1. `addBehaviors(Object obj):void` 此方法用于向指定的 DOM 元素添加事件监听器。它接受一个对象作为参数,其中键为事件选择器(selector),值为对应的事件处理函数。 **...

Global site tag (gtag.js) - Google Analytics