当前位置: 代码迷 >> JavaScript >> ExtJS 惯用
  详细解决方案

ExtJS 惯用

热度:555   发布时间:2012-10-30 16:13:36.0
ExtJS 常用

Ext?Core概述
简介
Ext?Core是一款具有多项功能的轻型JavaScript库,基于MIT许可为大家服务。在Ext?Core中有许多激赏的功能,在倡导快速Web开发的同时也本着高质量、可伸缩性的代码的指导思想进行着。Core库对DOM操作、Ajax、事件、动画、模板、00机制等的任务都有相应的支持。Core库基于MIT方式发布,无论是一般的动态页面和简单的应用程序都可选择使用。

下载?
可在本页面下载,也可以到Ext?Core主页面查找最新的版本来下载。本手册之PDF下载的完整版本,请转到这个地址。

引入Ext?Core
送到手上的Ext?Core有调试的版本和供发布时的产品版本。产品版本已经作压缩(就是消除空白符、硬回车和注释)和混淆的处理(所有局部变量重命名为短的名称,使用YUI?Compressor)。在开发阶段,你应使用的是-debug版本,这样才会看到未混淆过的错误信息。

要引入Ext?Core的开发版本,这样引入JavaScript文件就可以了:

<script?src="ext-core-debug.js"></script>
要引入产品版本(压缩并且gzipped后25kb),只需要省略掉“
-debug”:

<script?src="ext-core.js"></script>
完事!Ext?Core没有相关的CSS文件。

最简单的例子
完成Ext?Core的加载之后,拿下面的代码测试一下是否正确加载了:

Ext.onReady(function()?{
????Ext.DomHelper.append(document.body,?{tag:?
'p',?cls:?'some-class'});
????Ext.select(
'p.some-class').update('Ext?Core?successfully?injected');
});
关于
本手册的作者是Tommy?Maintz、Aaron?Conran、James?Donaghue、Jamie?Avins与Evan?Trimboli。译者根据基于GNU?Free?Documentation?License许可的原版于2009.
4.5初次释放版本来翻译,分设有简体中文和繁体中文(正体中文,格式是PDF)两种版本。维护以上两种中文的翻译版本的是Ext中文站(ajaxjs.com),frank是主要译者。文中许多部分取材于《Ext?3.x中文文档》。鉴于《文档》是frank与南宫小骏、善祥等诸多Ext爱好者之合力,特此说明。翻译若有不足之处,请立即联系我们。另提供PDF下载的完整版本,请转到这个地址。

元素(Element)
获取元素(Getting?Elements)
一份HTML文档通常由大量的装饰元素(markup)所组成。每当浏览器加载当前的html文档,html文档其中的每一个标签都被翻译为HTMLElement以构建装饰树的文件对象模型(Document?Object?Model,DOM)。你可以在浏览器的全局空间中找到一个称为document的变量,那个document就是DOM树的对象。document记忆了当页面加载完毕后而形成的每一份装饰元素引用。

document对象有一个重要的方法getElementById,允许在每个浏览中获取其中的HTMLElement对象。然而,直接操纵DOM来说还有许多要注意的问题。Ext?Core实现了Ext.Element类来封装(Wrap?around)各浏览器不同HTMLElement的对象。

Ext.Element占Ext?Core库的篇幅很大,其中方法就占据了大部份。因此我们将这些方法可分为下面几类:

CSS与样式(如setStyle、addClass)?
DOM查询或遍历(如query、select、findParent)?
DOM操控(如createChild、remove)?
元素的方位、尺寸(如getHeight、getWidth)?
你可以使用Ext.get方法创建Ext.Element的实例,达到封装普通的HTMLElement之目的。例如你有已一个id名为“myElementId”的元素,便可以这样获取:

var?el?
=?Ext.get('myElementId');
用Firebug执行以下代码后,观察Ext.Element身上的方法有哪些。有一点要注意的就是,你正在观察的是普通JavaScript对象,我意思是说无所谓的public与private的方法,它们均有在此列出,若有疑问可参考API文档。

var?el?
=?Ext.get('myElementId');
console.dir(el);

?
console.dir命令由Firebug提供,执行该可方便地列出某个对象身上有什么成员,这都是例于开发者阅读的形式显示的。你换可以通过折叠某个子对象以了解其牵连的属性。如图,属性显示是黑色的,方法
/函数是绿色的,构造器(constructors)或类(class)就是红色的。现在我对id为myElementId的段落元素进行操作:

var?el?
=?Ext.get('myElementId');
el.addClass(
'error');

这段代码作用后段落的字体颜色就变为红色,页面的CSS规则有error的样式类,属于error类的元素就会有红色效果:

.error?{
????color:?red;
}
下一小节(CSS类与样式)会简介关于处理元素的不同方式。

理解Flyweight
享元模式(Flyweight?Design?Pattern)是一种节省内存的模式,该模式的大概原理是建立单个全体对象然后不断反复使用它。?

Ext在启动的时候就创建了一个全局的Ext.Element对象专为Flyweight的设计服务。这个全局的Flyweight实例可以为Dom里面任何一个节点保存引用。要访问这种Flyweight的对象请使用Ext.fly方法。Ext新手可能会因Ext.
get()与Ext.fly()两者之间的用法而犯湖涂。

如果感觉这个Ext.Element元素是一直下去多次引用的,那么可以使用Ext.get方法;如果在一段时间内不需要存储元素的引用,那么就使整个库部共享的对象Flyweight的Ext.Element对象。通过Flyweight访问元素,用Ext.fly(
/*元素id*/)的方法。

再如上面那段落,我们撤销样式。

Ext.fly(
'myElementId').removeClass('error');

当执行这代码,Ext就复用现有的享元对象,不一定要建立一个全新Ext.Element对象。fly方法较适合单行的、一次性的原子操作(atomic?operation),就算你想将某个元素存储起来也是无效的,因为其它代码很有机会改变对象。例如,我们看看下面的代码:?

var?el?
=?Ext.fly('foo');
Ext.fly(
'bar').frame();
el.addClass(
'error');

frame()是Ext.Element包中的动画方法,产生高亮的效果,你可以估计一下,有什么现象出现??

答案是id为bar的那个元素会产生frame效果随后立即应用上error的CSS样式效果,那foo?id的元素可什么事情都没有发生,这是由于指向Flyweight对象的el引用已经被产生过frame效果的所使用。?

el就是bar元素,这是关于Flyweight享元用法的重要内容,如果你想搞清楚Ext.fly方法的用途适宜再看看这部份的内容。

Ext.
get?
Ext.
get()可接收这几种类型的参数,如HTMLElement,Ext.Element、字符型,返回的新实例。以下三种类型如下例:

var?el1?
=?Ext.get('elId');?//?接收元素id
var?el2?=?Ext.get(el1);?//?接受Ext.Element
var?el3?=?Ext.get(el1.dom);?//接受HTMLElement

Ext.fly?
Ext.fly在参数方面与Ext.get的完全相同,但其内置控制返回Ext.Element的方法就完全不同,Ext.fly从不保存享元对象的引用,每次调用方法都返回独立的享元对象。其实区别在于“缓存”中,因为缓存的缘故,Ext.get需要为每个元素保存其引用,就形成了缓存,如果有相同的调用就返回,但Ext.fly没有所谓的缓存机制,得到什么就返回什么,不是多次使用的情况下“一次性地”使用该元素就应该使用Ext.fly(例如执行单项的任务)。

使用Ext.fly的例子:

//?引用该元素一次即可,搞掂了就完工
Ext.fly('elId').hide();

Ext.getDom?
送入String?(id)、dom节点和Ext.Element的参数,Ext.getDom只会返回一个普通的dom节点。如下例:

//?依据id来查dom节点
var?elDom?=?Ext.getDom('elId');?
//?依据dom节点来查dom节点
var?elDom1?=?Ext.getDom(elDom);?

//?如果我们不了解Ext.Element是什么直接用Ext.getDom返回旧的dom节点好了
function(el){
????var?dom?
=?Ext.getDom(el);
?????
//?接下来干些事情……
}

CSS样式
通过学习markup装饰部分,我们已经晓得,装饰与document的紧密联系下如何透过Ext?Core较简便地取得数据。但进行document的布局又如何编排呢?是不是有一种方法可以控制布局也可以控制document的样式呢?答案便是用Cascading?Style?Sheets?(CSS)处理。CSS正是用来页面可视化信息和布局的语言。Ext?Core在方面真的是让我们用户感觉好使好用,易如反掌,――直接修改它就行了。

<style?type="text/css">

myCls?{
????color:?#F00;
}
</style>

...

<div?type="myCls">您好!</div>
上一例中我们赋予div元素“您好”的文本和让其颜色为红色(#F00)。

我们已经晓得Firebug,可以为我们带来页面开发上的种种便利。凡页面中的任意一元素上面右击,选择“Inspect?Element”(检测元素),弹出Firebug可以观察到dom树中真实情况,该元素是定义在哪里的。Dom树右边的面板就是对应该元素身上的样式。

?
如果你未曾熟悉Firebug的话,暂时放下这块建议先学习一下它。它仿佛就是Web开发的高级示波器!心血来潮地修改站点的样式抑或是调试站点的样式,“Inspect?Element”功能都贡献殊大。回到Ext中,我们看看Ext?Core中有哪些方法是为修改CSS所服务的。

addClass?
轻松地为一个元素添加样式:
Ext.fly(
'elId').addClass('myCls');
????????????????????
//?加入元素的'myCls'的样式
radioClass?
添加一个或多个className到这个元素,并移除其所有侧边(siblings)节点上的同名样式。?
//为元素添加'myCls'在所有侧边元素上删除'myCls'样式

//?all?sibilings.
Ext.fly('elId').radioClass('myCls');
removeClass?
移除元素身上一个或多个的CSS类。?
Ext.fly(
'elId').removeClass('myCls');?//?移除元素的样式
toggleClass?
轮换(Toggles,两种状态中转换到一个状态)
--添加或移除指定的CSS类(如果已经存在的话便删除,否则就是新增加)。?
Ext.fly(
'elId').toggleClass('myCls');?//?加入样式
Ext.fly('elId').toggleClass('myCls');?//?移除样式
Ext.fly('elId').toggleClass('myCls');?//?再加入样式
hasClass?
检查某个CSS类是否作用于这个元素身上。?
if?(Ext.fly('elId').hasClass('myCls'))?{
????
//?是有样式的……
}
replaceClass?
在这个元素身上替换CSS类。?
Ext.fly(
'elId').replaceClass('myClsA',?'myClsB');
getStyle?
返回该元素的统一化当前样式和计算样式。?
var?color?
=?Ext.fly('elId').getStyle('color');
var?zIndx?
=?Ext.fly('elId').getStyle('z-index');

var?fntFmly?
=?Ext.fly('elId').getStyle('font-family');
//?...?等等
setStyle?
设置元素的样式,也可以用一个对象参数包含多个样式。?
Ext.fly(
'elId').setStyle('color',?'#FFFFFF');
Ext.fly(
'elId').setStyle('z-index',?10);
Ext.fly(
'elId').setStyle({
????display?:?
'block',
????overflow?:?
'hidden',
????cursor?:?
'pointer'

});
//?带有动画的变换过程
Ext.fly('elId').setStyle('color',?'#FFFFFF',?true);
//?带有0.75秒动画的变换过程
Ext.fly('elId').setStyle('color',?'#FFFFFF',?{duration:?.75});?

//?...?等等
getColor?
为指定的CSS属性返回CSS颜色。RGB、三位数(像#fff)和有效值都被转换到标准六位十六进制的颜色。?
Ext.fly(
'elId').getColor('background-color');
Ext.fly(
'elId').getColor('color');
Ext.fly(
'elId').getColor('border-color');

//?...?等等
setOpacity?
设置元素的透明度。?
Ext.fly(
'elId').setOpacity(.5);
Ext.fly(
'elId').setOpacity(.45,?true);?//
????动画

//?附有半秒的动画过程
Ext.fly('elId').setOpacity(.45,?{duration:?.5});
clearOpacity?
清除这个元素的透明度设置。?
Ext.fly(
'elId').clearOpacity();
Dom游历
已知某个位置,我们要其附近位置的dom树中游历,是一件经常性的任务。Ext?Core里面就有这样跨浏览器的方法,允许我们在dom之中穿梭自如。再一次,CSS进入了我们的视野,使得干起复杂的任务时没那么痛苦。基于CSS3的选择符(选择器)在方面也尤其地干练!

拿以下的装饰做示范:

<style?type="text/css">

????.red?{
????????color:?#F00;
????}
</style>????
...
<div?id='elId'>
????
<ul>
????????
<li>a-one</li>

????????
<li>a-two</li>
????????
<li>a-three</li>
????????
<li>a-four</li>

????
</ul>
????
<ul>
????????
<li>b-one</li>
????????
<li>b-two</li>

????????
<li>b-three</li>????????????????
????
</ul>
</div>
这是一堆列表元素,要让其中的偶数行变红色。要如此优雅地实现该功能,Ext不是没有,键入命令如下:

Ext.fly(
'elId').select('li:nth-child(2n)').addClass('red');
结果如下:


我们已见识过游历DOM方面,依靠Ext?Core所带来的强大威力,――类似还有更多的,看看:

is?
测试当前元素是否与传入的选择符相符一致。?
var?el?
=?Ext.get('elId');
if?(el.is('p.myCls'))?{
????
//?条件成立

}
findParent?
定位于此节点,以此节点为起点,向外围搜索外层的父节点,搜索条件必须符合并匹配传入的简易选择符。?
Ext.fly(
'elId').findParent('div');?//?返回dom节点

Ext.fly(
'elId').findParent('div',?4);?//?查找4个节点
Ext.fly('elId').findParent('div',?null,?true);?//?返回Ext.Element
findParentNode?
定位于此节点的“父节点”,以此节点的“父节点”为起点,向外围搜索外层的“父父”节点,搜索条件必须符合并匹配传入的简易选择符。?
Ext.fly(
'elId').findParentNode('div');
up?
沿着DOM,向外围搜索外层的“父父”节点,搜索条件必须符合并匹配传入的简易选择符。?
Ext.fly(
'elId').up('div');
Ext.fly(
'elId').up('div',?5);?//?限5层的内查找
select?
传入一个CSS选择符的参数,然后依据该CSS选择符从当前元素下面,形成期待匹配子节点的集合,也就是“选择”的操作,最后以一个Ext.CompositeElement类型的组合元素的形式返回。如果以Ext.select()调用表示从document可是搜索。
//?返回结果的CompositeElement
Ext.fly('elId').select('div:nth-child(2)');
//?返回数组
Ext.fly('elId').select('div:nth-child(2)',
????
true);

//?整个document都会搜索
Ext.select('div:nth-child(2)');
query?
进行一次query的查询,返回DOM?节点组成的数组。可选地第二参数设置为查询的起点,如不指定则为?document。?
//?返回dom节点组成的数组
Ext.query('div:nth-child(2)');?
child?
基于送入的选择符,不限定深度进行搜索,符合的话选取单个子节点。?
Ext.fly(
'elId').child('p.highlight');??//?返回的类型是Ext.Element

Ext.fly(
'elId').child('p.highlight',?true);??//?返回dom节点
down?
基于该选择符,
"直接"选取单个子节点。?
Ext.fly(
'elId').down('span');??//?返回的类型是Ext.Element
Ext.fly('elId').down('span',?true);??//?返回dom节点
parent?
返回当前节点的那个父节点,可选地可送入一个期待的选择符。?
//?返回父节点,类型是Ext.Element
Ext.fly('elId').parent();??
//?返回父节点,类型是html?dom
Ext.fly('elId').parent("",?true);

//?返回父级节点,但一定要是div的,找到就返回,类型是Ext.Element
Ext.fly('elId').parent("div");
next?
获取下一个侧边节点,跳过文本节点。可选地可送入一个期待的选择符。?
//?返回下一个侧边节点,类型是Ext.Element
Ext.fly('elId').next();
//?返回下一个侧边节点,类型是html?dom
Ext.fly('elId').next("",?true);
//?返回下一个侧边节点,但一定要是div的,找到就返回,类型是Ext.Element
Ext.fly('elId').next("div");
prev?
获取上一个侧边节点,跳过文本节点。可选地可送入一个期待的选择符。?
//?返回上一个侧边节点,类型是Ext.Element
Ext.fly('elId').prev();
//?返回上一个侧边节点,类型是html?dom
Ext.fly('elId').prev("",?true);
//?返回上一个侧边节点,但一定要是div的,找到就返回,类型是Ext.Element
Ext.fly('elId').prev("div");
first?
获取第一个侧边节点,跳过文本节点。可选地可送入一个期待的选择符。?
//?返回第一个侧边节点,类型是Ext.Element
Ext.fly('elId').first();
//?返回第一个侧边节点,类型是html?dom
Ext.fly('elId').first("",?true);
//?返回第一个侧边节点,但一定要是div的,找到就返回,类型是Ext.Element
Ext.fly('elId').first("div");
last?
获取最后一个侧边节点,跳过文本节点。可选地可送入一个期待的选择符。?
//?返回最后一个侧边节点,类型是Ext.Element
Ext.fly('elId').last();
//?返回最后一个侧边节点,类型是html?dom
Ext.fly('elId').last("",?true);
//?返回最后一个侧边节点,但一定要是div的,找到就返回,类型是Ext.Element
Ext.fly('elId').last("div");
DOM操控
DHTML常见的一项任务就是DOM元素的增、删、改、查。鉴于不同浏览器的差别很大,搞起来会很麻烦,ExtCore就设计了一个抽离不同浏览器之间差异的API,并考虑了执行速度方面的优化。我们可以轻松地围绕DOM树做增、删、改、查的任务。先观察一下这装饰元素:

<div?id='elId'>
????
<p>paragraph?one</p>
????
<p>paragraph?two</p>

????
<p>paragraph?three</p>
</div>
渲染出来这样:

?
这时我们为其加入一个子节点“elId”:

Ext.fly(
'elId').insertFirst({
????tag:?
'p',
????html:?
'Hi!?I?am?the?new?first?child.'

});
插入后是这样:


小菜一碟吧!?我们再操练一下Ext?Core强大的API功能:

appendChild?
把送入的元素归为这个元素的子元素。?
var?el?
=?Ext.get('elId1');
//?用id指定
Ext.fly('elId').appendChild('elId2');
//?Ext.Element添加
Ext.fly('elId').appendChild(el);
//?选择符组合地添加
Ext.fly('elId').appendChild(['elId2','elId3']);
//?直接添加dom节点
Ext.fly('elId').appendChild(el.dom);

//?添加CompositeElement,一组的div
Ext.fly('elId').appendChild(Ext.select('div'));??
appendTo?
把这个元素添加到送入的元素里面。?
var?el?
=?Ext.get('elId1');????
//?'elId'添加到'elId2'里面
Ext.fly('elId').appendTo('elId2');?
Ext.fly(
'elId').appendTo(el);??//
????添加到Ext.Element?el
insertBefore?
传入一个元素的参数,将其放置在当前元素之前的位置。?
var?el?
=?Ext.get('elId1');????

//?dom节点在前面插入
Ext.fly('elId').insertBefore('elId2');
//Ext.Element?el在前面插入
Ext.fly('elId').insertBefore(el);
insertAfter?
传入一个元素的参数,将其放置在当前元素之后的位置。?
var?el?
=?Ext.get('elId1');????

//?dom节点在后面插入
Ext.fly('elId').insertAfter('elId2');
//?Ext.Element?el在后面插入

Ext.fly(
'elId').insertAfter(el);
insertFirst?
可以是插入一个元素,也可以是创建一个元素(要创建的话请使用“DomHelper配置项对象”作为参数传入),总之,这个元素作为当前元素的第一个子元素出现。?
var?el?
=?Ext.get('elId1');????


//?插入的dom节点作为第一个元素
Ext.fly('elId').insertFirst('elId2');??
//?插入的Ext.Element作为第一个元素
Ext.fly('elId').insertFirst(el);
????????
//?用DomHelper配置项创建新节点,新节点会作为第一个子元素被插入。?
Ext.fly('elId').insertFirst({
????tag:?
'p',
????cls:?
'myCls',
????html:?
'Hi?I?am?the?new?first?child'

});
replace?
用于当前这个元素替换传入的元素。?
var?el?
=?Ext.get('elId1');????

?
//?'elId'去替换'elId2'

Ext.fly(
'color: #80000

  相关解决方案