Ext 4概述
Ext 4有志诚成为Web程序其革命性的开发平台。框架中的每一个首要的组件几乎都作了改善,而且属于相当大幅度的改善。对于Ext3来说——4.0许多组件以及子系统都是表现得焕然一新!本指南会向您提供有关Ext3到Ext4期间变化所呈现的一方面。
如果您在阅读本文档时正好发现任何问题,请积极反馈,或来到Sencha论坛《迁移Ext3到Ext 4》的帖子还有来到Ext中文网之JS堂社区反馈吧!
一般性问题
该文档通用于[#ext-core Ext Core]及[#extjs Ext JS]。
Ext 3的兼容性
我们几次更新Ext JS累积下来,感觉当然就是第四版的变化幅度最大。第四版带来了许多内容,这些内容并不兼容于Ext3。然而,我们尽力可以做到跟更前个版本最大化的兼容。
JS兼容化文件
加载Ext4完毕后,你可选择加载这份兼容化文件。该文件的目的在于提供兼容Ext3的简写方式和覆盖新参数为适合旧版的参数。
注意: 此时此刻兼容化文件尚未释出可用,不过应该会在发布4.0正式版之前提供给大家。
沙箱模式
Ext 4完全基于沙箱设计的,因此可以让旧版的Ext与Ext4”同处一室“,在同一个浏览器运行时中做到兼容(译注:有一个桌面的例子,仍使用Ext3代码)。从JavaScript角度看,原来所有修改对象原型的方法已被转移,转移到全局对象Ext之下。现在只需要建立一个Ext对象的引用,分配不同的名称,就可以从以前旧版本的Ext中区分开来……
在标签markup/CSS方面,由于Ext4采用了Compass和SASS框架并通过模板生成CSS,所以很容易设定一个前缀,供CSS规则之用,比如Ext.baseCSSPrefix属性就是对应的前缀。结果,要与旧版Ext的CSS区分开来,也不是什么难事了。
包与命名空间的更新
在重构过程中,全体类和包的结构已经发生了变化。如何变化将是根据严格的命名转换来规范的,这一点对于重构的结果非常重要,以便于我们能更轻松地查找某一个类。例如Ext3的Button类、CycleButton类和SplitButto类就连同其他类归类在/widgets中。尽管不同层次的对象却也直接地命名在全局对象Ext身上。
在Ext 4,每一个类根据其特性的相似来决定其包的位置。虽然只是命名上的变化,但比起Ext3能更精确地描述对象。同样拿Button按钮为例子,Ext4的类这样分配:
单独设一个包src/button/
代码划分出一个新的命名空间
改名,如Ext.SplitButton→ Ext.button.Split
为了尽可能地照顾Ext3的旧命名方式,Ext4的类有一个特殊属性称作“alternateClassName”,通过这个属性就可以让Ext3遗留项目采用Ext4新的类库。例如alternateClassName: 'Ext.SplitButton'。当然,我们很希望你完全采用Ext4开发方式。
Ext Core
新型类系统
参考资源
Ext JS 4的倒数:动态加载和新的类机制(上)
Ext JS 4的倒数:动态加载和新的类机制(下)
Ext JS 4 的类机制主要围绕传统OO模型而设计,弥补了Prototype OO不足。虽然性质上仍为模拟的手段,但包含了比较完整的OO特征,并且保持对旧Ext3类机100%兼容。Ext JS 4(连同 Ext Core)提供的新功能有:
继承方面Ext.defined代替了原来Ext.extend的写法。
自动计算依赖关系及动态类加载。
多态
静态成员
为配置项自动生成的getter/setter方法
ext4-class-system.jpg
如何写类?
你仍可在Ext4使用new ClassName()的语法,不过推荐使用Ext.define()函数定义新类。利用Ext类系统显式定义好的类,将有什么不同呢?关键字new仍然可用,可没太大的特别。Ext.define还有一个好处,自动创所须的建命名空间,从而免去声明命名空间的一步。
这里是利用新语法定义的一个新Ext.Component子类。
// Ext 3:
Ext.ns('MyApp'); // 命名空间在Ext 3是必须的
MyApp.CustomerPanel = Ext.extend(Ext.Panel, {
// etc.
});
// Ext 4
Ext.define('MyApp.CustomerPanel', {
extend: 'Ext.panel.Panel',
// etc.
});
加载类
Ext 4终于引入了动态类加载的系统了,虽然你可以选择使用,也可以选择忽略,但无论怎么说,终于考虑这点,希望社区不再利用此缺点来指责Ext之庞大。首先交待一下提供哪些功能:
动态加载(Dynamic loading):运行时期间,Ext内部会根据依赖树的关系异步地下载类文件。这意味你不用再页面上手动引入include子类的HTML标签就可以加载你所需的资源,同样不会造成阻塞。开发期间,动态加载的灵活性远比关心页面加载速度的意义打得多。
动态生成build文件(Dynamic build generation):对于产品化,很希望就是打包为一份文件,亦即build files。由于Ext已经清楚掌握依赖关系,所以很容易导出一个依赖关系图,适合于某些自定义build配置。更开放的是,不限于Ext的命名空间,只要按照Ext类规范写类,Ext就会计算它们的关系。在不久的将来,Ext开发者会享用”一键化“的build服务,而且一切都是经过智能计算的,决没有冗余的代码。
动态加载必须有两个前提条件,一是打开Ext.define;二是在写类的时候须清楚指明依赖关系,当中关系所涉及两个属性说明如下:
requires: 所依赖的类。保证当前被实例化之前其他类就绪。
uses: 可选的依赖,不一定必须的(上面requires是指定必须的模块)。uses的类可以异步下载,不限于一定要在类实例化之前(因为异步的,可能之后)。
多态Mixins
多态(或译作“混元”)可以为现有的某个对象注入客制功能提供一种灵活的方式。mixins配置项,包括实例化类期间,允许给类原型“混入”新的能力。这与Ext.override函数作用类似。尽管该方法不会覆盖现有的方法,就像override那样不会直接覆盖,但是该方法的参数还是。Mixins语法如下:
Ext.define('Sample.Musician', {
extend: 'Sample.Person',
mixins: {
guitar: 'Sample.ability.CanPlayGuitar',
compose: 'Sample.ability.CanComposeSongs',
sing: 'Sample.ability.CanSing'
}
});
静态成员(Statics)
通过statics这个属性可以设置类的静态成员。
配置项 Config
Ext之中我们用术语“配置项(config items)”来表示任意的属性,这些属性在类原型(class prototype)都可以明确找到。有了配置项可以通过代码的调用对API读或者写。Ext 4在这点上基本没有什么问题,唯一作出新内容的便是带来了特定项“config”。当类定义中加入config属性,其对象所包含的内容指的就是“配置项”,而且强调一点就是,围绕配置项自动产生getter、setter、reset和apply方法,其中setter还提供模板方法自定义setter逻辑。基本示例代码如下:
Ext.define('MyClass', {
config: {
title: 'Default Title'
}
});
……根据以上介绍的机制,自动生成下列方法:
title: 'Default Title',
getTitle: function() {
return this.title;
},
resetTitle: function() {
this.setTitle('Default Title');
},
setTitle: function(newTitle) {
this.title = this.applyTitle(newTitle) || newTitle;
},
applyTitle: function(newTitle) {
// 自定义代码
// 如Ext.get('titleEl').update(newTitle);
}
Env命名空间
提供浏览器和操作的相关信息,还有告诉我们现代浏览器提供了什么功能。
Ext.env.Browser
该类提供了全部浏览器的元信息(名称、引擎、版本、是否Strict模式等等) ,用于全局对象Ext。
Ext.env.FeatureDetector
这是一个在Ext3中没有类,完全新的功能,其功能在于检测浏览器特性如何,主要针对现代HTML5和CSS3的特性,包括移动平台在内的特性列表,有:
CSS 变形、动画、转换
Canvas、SVG、VML
触控能力、方向
导航 Geolocation
SqlDatabase
Websockets
History
Audio
Video
Ext.env.OS
提供当前主机操作系统的信息(包括移动OS的列表)。
语言包(Lang Package)
同样的功能在Ext中都会有,但这是一个新的包,之所以定义为一个新的包,是为了尽量不会影响到JavaScript的对象原型。尽管在对象原型中设置方法会比较方便,但是如果引入了其他JavaScript一起,很难说会不会构成冲突或者影响的说。再者,如果日后ECMAScript规范作出了修订,会不会与Ext所定义的构成重叠呢?所以,要解决以上顾虑,我们还是把语言方法的命名空间定义在Ext对象之下,避免在对象原型身上定义的成员。
实际上虽然没有分配一个“lang”的这么一个命名空间,但是还是在源码树(Source Tree)中划分了一份文件专门定义语言增强函数。前后变化如下:
Array → Ext.Array
Date → Ext.Date
Function → Ext.Function
Number → Ext.Number
Object → Ext.Object
String → Ext.String
请注意在兼容化文件中,仍会对核心对象的原型挂载方法之引用。重申一下,要真正升级到Ext 4并摆脱Ext 3旧的调用方式,就必须移除兼容化文件,最后升级到新的命名空间形式。
Ext.Function
Ext 4的函数原型Function prototype改变后,怎么调用?最主要的一点就是命名上发生变化,如Function.createDelegate()和Function.createCallback()分别重命名为 Ext.Function.bind()和Ext.Function();Function.defer()变化为Ext.Function.defer()。由于使用频率较高,我们在Ext对象上添加了快捷访问方式,便是Ext.bind、Ext.pass和Ext.defer;其余的函数方法像createSequence()和createInterceptor()就取消了,但引入新方法createBuffered()和createThrottled(),可以看看有什么用途。
如下是一些语法糖说明前后之变化:
// Ext 3:
myFunction.createDelegate(this, [arg1, arg2]);
myFunction.defer(1000, this);
// Ext 4:
Ext.bind(myFunction, this, [arg1, arg2];
Ext.defer(myFunction, 1000, this);
Ext JS
参考资源
Intro to Ext 4 (video
Ext 4 Architecture (video)
通用问题
适配器(Adapters)
之前的各个Ext版本中都可以透过使用适配器(adpaters)的方式转换第三方的JavaScript库为我所用。Ext4的话就没这支歌仔唱了。改朝换代后,Ext JS应用程序的底层库唯一限定为Ext Core。不过我们依然可以继续让Ext Core与别的JS库共存于一个JS运行时(实际上这就是为什么一些JavaScript对象其原型的方法都被<a href="#lang">移至到Ext中</a>去的原因)。不同的就是Ext不依赖于其他JS的底层库了。
ARIA
为达到ARIA用户友好性的支持,而且是全面的支持,Ext对每一块组件都细心打造进而在这方面加强之。Ext.Component新设有ariaRole角色的配置项属性,默认是“presentation”(该角色仅表示为可见的并没有更高的含义,也没有用户交互的功能)。然后就让后面更高层次逻辑来覆盖它。例如,Ext.button.Button对ariaRole覆盖,标识为“button”,就表示这个是一个执行按钮语义的这么一个物件,这对屏幕阅读者(Screen Readers)非常有用。不论按钮外观上表现得如何,API在实际会在渲染按钮的过程中,对其标签中添加上一项HTML属性:role。总之,伴随着ARIA的增强,Ext于用户友好性(Accessibility)方面的提升大家应该是有目共睹的。
另一项ARIA重要的特性便是Ext.Component内建了aria-disabled支持。这一切都是自动进行的。当HTML标准属性aria-disabled激活的话,就会为屏幕阅读者(Screen readers)表示出某些功能化UI元素的激活状态。
Data
3.x的数据已经变化了不少,4.x继续重构并加入更多新的元素。但其中一点必须提到的,便是4.x的数据被设计成为能够与SenchaTouch共享的代码,也就说不论ExtJS或SenchaTouch使用同一套类库。有关这么方面的教程已经有不少了,这里我们就一些必要的背景内容和新特性作一番介绍。当然,如果尚未了解的读者还是建议你们阅读一下之前的教程或资讯:
参考资源
Proxies (blog post)
Ext JS 4的倒数:程序员预览
Ext JS 4 数据包的演示例子
客户端数据层的革新:引入ActiveRecord模式
概述
针对Ext 3的兼容化文件使得数据包得以连续可供Ext3使用。论变化最大者,有Store和Proxy和新引入的Model。Model实质便是Record的升级。
Store与数据格式无关,即不再存在JsonStore/XmlStore之分。其加载和保存数据都经过Proxy来执行,而Proxy的数据由来自于Reader或Writer是里。Store可执行客户端的多排序、动态过滤和动态分组,并与服务端同步亦可。
Proxy既可附加到Store也可直接附加到Model,附加到Model的好处就是省去了处理Store的步骤。可以在配置Readers和Writers时候配置Proxy,从而来解码或编码来自服务器的数据。
Model 也旧版的Record和相似,加入了关系、验证和更多的内涵。
另外,Ext JS 4 也可以将Model持久化到本地存储,利用全新的LocalStrorageProxy类就可以无缝地把数据保存的HTML5的本地存储。
Draw
Draw包是全新的包没有一点Ext旧的包袱。Draw包具备自定义的绘图能力,通过抽象Canvas、SVG与VML引擎特性就可以根据当前浏览器的运行时选择最佳的绘图方式。Ext 4的<a href="#charting">图表</a>就是依赖于这个Draw包,不但如此,Draw包还可以拓展至其他类型的图形绘制。主要特性如下:
基于HTML5 标准
渲染原语形状文本、图形、渐变
操控颜色、矩阵转换等等的类库
Ext.draw.DrawComponent
继承自Ext.Component
检测特性调优引擎
可自定义引擎调优顺序
可参与布局
通过Ext.draw.Sprite 内建块管理
抽象的绘制元素
常规化引擎API语法之间的差异
属性
事件支持(通过继承Observable)
变形(旋转、转换、缩放)
经由Ext.fx实现了动画
SpriteComposites
图表与图形化 Charting & Visualization
图表Chart不是好端端地用Flash做的吗?现在4.0却对Flash大声“say no”——回归网页标准的处理手法,要用Canvas/SVG/VML来做代替了Flash,命名空间就是Ext.draw.*。随着改进一些复杂的JS动画也成为可能。和Dojo一样终于有了属于自己的图形类库。虽然新图表可以顺利支持到IE6的浏览器,不过还是希望不要太冒进,能够继续使用3.x的Flash。图表引擎会自动选择适合当前浏览器的渲染引擎。无论采用哪一种的图表底层引擎,全体图表的函数都定义为同一种的API。这对用户开发至关重要。
参考资源
SenchaCon Overview (video)
SenchaCon Overview (slides)
working-with-charts.gif
Fx
Ext 3的Fx类提供了一组有用的元素特效效果(平滑、高亮、渐显等)。Ext 4基本上依旧不变,而且在简单的元素效果的基础之上,还有突破的发展,例如通过Animator类,可协调负责页面上同时运行的多段动画。再例如,无论调整大小还是定位都可以使用Fx”Target“类选择目标(全称Ext.fx.target.*),这为创建动态UI打开了许多新的方式方法。
Layout
参考资源
Ext 4 Layouts (video)
Ext 4 Layouts (slides
ComponentLayout
ComponentLayout是一种新型的布局方式,许多复杂的组件就采用这种布局(与之对应的为ContainerLayout,“ContainerLayout”——传统基于容器布局的新名字)来计算内置元素的大小尺寸,以响应resize的调用。Field字段组件的FieldLayout布局,关于labell控件和input元素控件的大小尺寸和定位都是来自于ComponentLayout的逻辑。
FormLayout
Ext 4已经没有这种FormLayout了。请参阅[#form-layout Layout]的Form部分内容以了解更多。
BorderLayout
Border layout在Ext4或者Ext3中都是毫无差别的(即完全兼容)。
Panel的头部Header现在可垂直方向布置了,也就是说折叠一个垂直方向的头部时可以选择在东面或者西面来折叠,旋转九十度也没有问题(乃益于Ext 4新的<a href="#draw">Draw包</a>)。Ext3中的头部实质乃元素而已,而Ext4的却特有一个已经成熟的Ext.panel.Header实例,并有若干的方法。你可以使用布局的新方法getPlacerHolder获取头部对象。当然,作为Container的子类,Panel自然拥有全体Container的方法。对于第一次显示的是闭合状态的布局,则不会渲染头部组件对象。
另一个细微的差别就是已经不再支持cmargins配置项了。如同展开的面板那样,Header容器现在是相同的边距(margins)。这使得创建布局的时候,不管组件闭合的状态还是展开的状态,看上去都更一致。
从更加灵活的布局和制定布局这两点角度出发,现在BorderLayuout内部可允许嵌套HBox和VBox方式的布局来创建边界管理(the bordered arrangement)。
Component
普通的组件,只有设置其floating:true的话便变为一个“浮动”组件,浮动于文档流(document flow)之上。变为浮动之后,可对组件进一步配置,可否拖动、可否调节高宽等问题都可以配置。甚至可以作为子项加入到别的容器中去,但就是只是浮动在其上面,不参与布局运算。
全体浮动组件均有一个由ZIndexManager提供的z轴索引z-index。ZIndexManager来自于Ext 3的Window Group。一般情况下,单例Ext.WindowsMgr管理器负责管理像Windows这类浮动的组件。调用窗体对象身上的show()方法会在对document中进行渲染并显示。除此之外,调用窗体的toFront()或者toBack()方法都会涉及ZIndexManager。
参与容器渲染的浮动组件,虽然是浮动的,但必定位于容器内。渲染的时候就会先获取ZIndexManager之引用,然后查找需要z-index管理的父级容器。一般而言,单例Ext.WindowMgr将会提供一切信息。不过如果浮动的组件是一个浮动容器的后代,如Window的话,那么这个Window会创建一个其专用的ZIndexManager实例,然后其下辖的浮动组件则会相对于这个Window的Z-index来进行管理。
现在Ext中可谓提出了新的形式,通过z-index作为凭据来管理浮动的容器,无论容器多复杂,都可以快速地控制,也避免了组件之间的冲突影响。例如一个例子,窗体中的combo下拉箱子就总是在那窗体上,不影响其他层。
Form
Layout
Ext 3时代我们FormPanel利用FormLayout来定位field标签,input控件,错误提示等等任务。但一个重要的消息就是Ext 4的FormLayout取消掉了,取而代之的将是新成员FieldLayout(为<a href="#component-layout">ComponentLayout</a>的一子类)。标准布局则统一管理基础服务而这个FieldLayout又专门为字段标签控件所服务,而样的结果,只要是标准布局,就可以变为具有表单特性的布局。总之就是希望灵活性方面来个大跃进。
尽管标准布局就可以包含表单了,但是仍提供一个表单面板FormPanel,其容器的布局默认是anchor。
FieldContainer
为管理表单布局,Ext引入了新的Ext.form.FieldContainer类。这不但是一个标准的Ext.Container类,而且还是在Ext.Container的基础上加入标签(label)控件和错误信息等的这些考虑要素。这些label和错误信息的配置方法则与Ext.form.Field的无异,都是同一套API。就像真实字段输入控件自动拉伸占据空白空间那样,容器下子组件都会自适应尺寸。这样,在表单中加入复杂的组件也可以美观地分组,并且让表单的字段控件对齐起来。
Field as Mixin
长久以来要为非Field组件加入字段式的能力如布局、数据验证、值管理等等是一道难题。最简单的方法就是直接继承于Ext.form.Field从而获取相应的能力。虽然简单可行,但却破坏了原组件的继承链。究其原因,在于Ext或JavaScript只能提供“单根继承方案”,无法直接实现多继承。当然这属于Ext3的困窘,于Ext4中这一切都将成为过去,通过提供多态<a href="#class-mixins">mixins</a>的支持,能够让我们告别旧有只是复制Fields对像到类原型(Class Prototype)的拙劣手段。
Field被设计为多态类,可混入到其他主类上,结果就是可让任意组件拥有Field API的全部能量。当然你也可以根据需求来修改Field的具体行为,例如重写getValue方法和setValue方法。
Validation
一个常见的场景便是对用户输入的数据马上进行有效性的检测。早在Ext 3就有表单验证了,前提是打开FormPanel的monitorValid选项。但是打开改选项后,每秒钟都对表单进行验证,所以显得十分的慢。
Ext 4不能容忍这点不足,所以重新设计过新的事件流如下:
输入框控件随时会侦听来自浏览器的事件,就是为检测内容有什么变化。用户一输入内容,即打字输入、剪贴、复制、拖动文本到输入框都会使得输入框内容发送变化。我们封装这些浏览器事件为changeevent事件以检测输入框的变化(下面会有详述这部分细节)。
一旦改变值,每个字段就会立刻对其自身进行验证。当字段的有效性从无效的有效性转变为有效的有效性之时,便会触发validitychange事件,反之亦然。
字段触发validitychange事件后,又会导致表单范围内的有效性检测,BasicForm触发其自身的validitychange事件。
新的事件流可以立刻向用户反馈用户的输入情况,之所以迅速是因为新事件的性能比过去轮询(polling)的机制快得多。故所以,事件流的方式将是默认的方式(Ext 3却不是,必须显式启用)。当然你也可以禁止事件流的方式。
然而存在某些特殊的情况,轮询的价值似乎值得重新考虑。一些浏览器(例如Opera和一些老版本的Safari)处于edit mode的时候(通过鼠标右键剪贴或粘贴时)总是不能触发检测事件。要解决这类问题,你可以打开FormPanel的pollForChanges参数以允许通过轮询检测字段的变化。触发器仍如上述事件流的一般。——不得不说轮询的做法性能上不好,但比起Ext 3轮询的强度则没那么严重,因为每次轮询只是对值的观察,而没有繁重的数据验证的参加(指值解析、转换和正则模式匹配等的验证)。
当检测到字段发生变化时,就会对字段内容进行数据验证(假设已打开validateOnChange)。检测内容变化的浏览器事件多种多样,都保存在checkChangeEvents参数中,我们可以访问该参数来获取该事件名称。根据浏览器的不同,可能出现的checkChangeEvents值有:
对于InternetExlorper而言checkChangeEvents为change和propertychange。
对于其他浏览器而言checkChangeEvents为change、input、textInput、keyup。
两点所列出的大体上包含可以检测到的用户输入变化的事件。几乎可以支持到全体可支持浏览器,然而,还是有一些情形不能检测变化,列出如下:
Safari 3.2或更老的版本:鼠标右键剪贴或粘贴,拖到文本到textareas。
Opera 10和11:拖到文本到输入框和textareas,鼠标右键剪贴输入框和textareas的内容。
Opera 9: 除了Opera 10 and 11提到的外,还有用鼠标右键粘贴输入框和textareas的内容。
(译注:Oprea的QA咋留着这么多bug……:))如果你必须要通过轮询才能检测到值发生变化的话,你可以打开FormPanel的配置项pollForChages和配置项pollInterval,或者设置一计时器不停调用startPolling()方法和stopPolling()方法都可以检测到。
Ext 3支持按钮的formBind属性,目的在于可以表单验证对在表单元素范围之外的按钮控制其enabled/disabled状态。Ext 4则不限定在表单验证,而是拓展至FormPanel中任意的组件。
FieldDefaults
旧Ext 3的FormLayout包办了全部字段的在表单怎么显示的问题,如hideLabels、labelAlign等等,都是FormPanel的配置项属性。由于Ext的表单容器采用标准布局,不存在FormLayout,要指定普通字段的布局属性的话,就要进入层层的容器或字段,将会十分复杂。故所以FormPanel特别提供一个fieldDefaults对象,指定的值供全体字段对象所使用,不论嵌套多少层的FormPanel。
BasicForm
Ext 3的BasicForm用途不是很广,只是在FormPanel内部偶尔用一下。Ext4的话BasicForm重新打造得更为灵活和易于扩展。新Basic不再需要一个容器以分配元素,也不需要其所在的容器手动通知BasicForm加入或删除字段。也就是说,它完全与FormPanel解耦,有条件在任意容易中发挥管理表单字段的能力。
数据表格(Grid)
这次升级Ext 4全部重写了Grid组件。显然,诸多理由和原因迫使我们升级Grid,但Ext 4 Grid向后兼容方面真的很难顾全。为此,我们将会提供一份关于Grid在Ext3升级到Ext4的指南。
智能化渲染
旧Ext JS 3 Grid工作起来还是蛮不错的。但透过“最小公分母(least common denominator)”的方法论来确定其各种功能的话,很容易带来一点不足的就是,伴随着Grid的每一项功能,都会生成大量的HTML Markup产生。我们不得不面对这个问题。于是在ExtJS 4中,规定Grid的每一项功能,只会根据开发人员设定与否,才会渲染出与之对应功能的Markup在页面上。Grid默认启动时只有为数不多的Markup而已。这样设计API的结果,便是在渲染页面以及Grid整体效能这双方面均得到极大的提升。
标准化布局
渲染流水线得到了改善,Grid的其他方面亦齐头迈进,不甘人后。许多Grid的部分都被规划成为单独、清晰的Component组件,整合到标准的布局管理系统中,并非旧版中直接处理内部Markup、CSS的那种方式。这使得API可以联合框架的其他强大的特性,进而来统一Grid的渲染流程。而这些过程,仍维持在精确到象素级别水准(pixel-perfect)的UI体验。
例如,新的HeaderContainer类就很能说明这个问题。Ext3中的列头部(Column headers)整合到Grid的话感觉是比较生硬的,因此不太容易客制化。Ext4的列头部作出改进,其所使用的HBox标准布局就能够让你在每一列上输入灵活的flex值。
扩展新功能
在Ext JS 3里面为Grid加入新功能,一般API接口方面有良好的考虑。但现在来看,却没有一种清晰的流程方法去指导,显得比较乱。有时通过写插件(Plugins),有时就写子类。总之扩展Grid的话可能会比较复杂。要解决上述问题,实质就是提供一种彻底灵活的选项操作。ExtJS 4将引入全新的一个Grid基类,称作Ext.grid.Feature。通过继承这个Feature类,对任何Grid其所在模板(Template)进行修改,就可以控制当前Grid视图生成的Markup结果。Features类跟旧版的GridView相似,但能力更强,也更为有用。之所以有用和强大,是在于其对延续Grid功能这点上表现得更为简单和适配。Grid里头的一些功能如RowWrap、RowBody和Grouping都是Fetures之子类。
Ext 4 grid相关功能的演示例子有如下:
RowWrap
RowBody
Grouping
Chunking/Buffering
虚拟滚动
Ext 4 Grid已经可以做到原生支持“按需加载(load-on-demand)”的数据视图了。虽然这是个虚拟视图,但是的确可以能够做到数据的缓冲。无论上百条抑或达上千笔的数据,都可以保证在Grid轻松显示。无疑,这将大大扩充了Grid数据处理能力。
编辑单元格控件
我们依然拿旧版对比一下。Ext 3里面要编辑Grid单元格,就必须制定EditorGrid类。通过继承方式可能不太灵活,于是Ext 4就否决了继承的方式,而是采用“插件化”的方式。通过Ext JS4的Editing插件可以自由绑定到任意的Grid的实例,对于全体任何类型的Grid均可使用。于是乎,此举又为提高“灵活性(flexibility)”添泼了一抹浓彩。此外,对于Ext 3中很受大家所欢迎的一款扩展:RowEditor,在这次发布我们也将RowEditor正式加入的Ext 4包中去,成为标准类库的一员。
DataView
GridView的父类更改为DataView。这样做的好处不仅减少了代码量,而且使得Grid更容易制定。因为可以直接发挥DataView的选区模型,应用到任意一种的视图,包括那些非连续的选区,例如通过键盘Home、End、PageDown和PageUp所产生的选区。
面板Panel
支持了边界接触(Docking)
Panel的改变之一便是通过面板特定的组件布局类(a panel-specific ComponentLayout)来负责管理其边界内所接触的元素项。面板body元素会铺张至任何空白的位置。任何组件都可以通过设置目标面板的dockedItems配置项属性来相接触,而且对方面板的dock属性也要与之设置好才行。如此一来,Ext3中困难重重的水平界工具条现今已大幅改进其灵活性,在Ext4中轻而易举地实现上述功能。
头部Header的改进
头部Header 现今为容器子类的第一类公民,从而获得子组件管理与布局的特性。你可以设定headerPosition的配置为 'top'、'right'、'bottom'或'left'的其中之一来决定和ader所依靠的位置(new docking support)。
Tool工具按钮(即像关闭、最小化此类的按钮)虽然在Ext3中都有,不过现在是属于Component的子类了,显得更灵活。
Resizer
Ext很早就有调节大小的控件,但只为DOM元素服务。现在Ext 4任意组件也可以透过Ext.resizer.Resizer达成调节大小的一方面功能。这对浮动的组件比较有用,或者说没在Ext容器体系以外渲染组件的时候,将会派上用场。
只要设置组件resizable:true的配置项,那么将会分配多个调节手柄到组件的边界上。默认用一个代理元素来产生调节大小的效果,mouse up之后就会真正让组件的大小进行变化。具体的调节行为可以通过修改配置项对象resizable,——这个对象便是Resizer类的参数对象。
ComponentDragger
Ext一向支持多种方式的拖放支持,不过尚在DOM元素的级别。Ext 4改进后,新引入的Ext.util.ComponentDragger提升到组件级别,使得组件的拖动更简单。ComponentDragger对浮动组件比较有用,对非容器模型的UI控件也是有的。
只要设置组件的配置项draggable:true,这个组件就可以通过鼠标来拖动了。Windows本身就是可拖动的。拖动期间,被拖动的dragger实际是一个空白的“幽灵”,鼠标松开后,面板或窗体移动到目的地位置,然后这个“幽灵”也会消失。指定draggable的配置项可以修改dragger行为,该配置对象同样适用于ComponentDragger的配置对象。
分割栏 Splitter
箱子布局HBox和VBox都可以包含Ext.resizer.Splitter组件,用于调整箱子之间的尺寸。最小和最大的尺寸都可以支持的。默认下,对箱子布局其中一个flex项进行调整大小的话,就会把原来的flex的值变为精确的像素值,flex值将会删除。如果不想这种情况出现,可以配置maintainFlex:true就可以保持flex值,哪怕在调整大小操作之后。但这只适用于分割栏划分两块中的其中一块。
TabPanel
与其他众多Ext的组件一样,组成一个TabPanel的主要部分,已被分解并成为Ext4组件之第一公民。Tab本身在Ext3只是若干DOM元素,现在Ext4中却是重新认识Tab为一个”按钮“,容纳这些Tab的容器则就是一个容器。各方面显示,4.x的TabPanel比起Ext3提升的灵活性是显著的。
以上的做法,就是从包含内容的子面包中分离出来这些tabs,形成不同的小组件。正因为这样的分离,我们现在可以允许了tab面板中显示标题titile、工具按钮等在旧Ext3中无法想象的功能特性。
工具条 Toolbar
Toolbar现在为容器之第一公民了,加入新组件或自定义Toolbar布局的话,比起Ext3来得更加容易。
主题(Theming)
承蒙厚爱,Ext之主题一向被认为出彩的地方,看起来很好,可修改起来却不容易。虽然Ext 3通过分离结构以及可视化样式表改善了主题制定任务,但是尚不足够,仍有冗余、繁杂的浏览器私有特性以及一个关键,便是CSS本身语言不足所带来的问题。
参考资源
Ext 4 Theming (video)
Ext 4 Theming (slides)
Compass与SASS
Ext的主题样式借助了新工具来实现的,内部透过转换Compass和SASS来作为主要CSS输出工具。SASS为CSS标准的超级,加入了许多新的高级功能。
内嵌选择器
变量
多态
选择器的继承
编译和压缩
哪些组件需要的样式就导出,不需要的样式就不导出
Markup的不同
Ext现在支持了特定版本或浏览器的组件markup,比起Ext3跨越了一大步。
文档
支持类更多的新元素(requires、mixins等)
支持遗留项元素
记录浏览历史
内涵例子、视频等
关注话题
多框架和版本的支持
本地搜寻
Ext 4有志诚成为Web程序其革命性的开发平台。框架中的每一个首要的组件几乎都作了改善,而且属于相当大幅度的改善。对于Ext3来说——4.0许多组件以及子系统都是表现得焕然一新!本指南会向您提供有关Ext3到Ext4期间变化所呈现的一方面。
如果您在阅读本文档时正好发现任何问题,请积极反馈,或来到Sencha论坛《迁移Ext3到Ext 4》的帖子还有来到Ext中文网之JS堂社区反馈吧!
一般性问题
该文档通用于[#ext-core Ext Core]及[#extjs Ext JS]。
Ext 3的兼容性
我们几次更新Ext JS累积下来,感觉当然就是第四版的变化幅度最大。第四版带来了许多内容,这些内容并不兼容于Ext3。然而,我们尽力可以做到跟更前个版本最大化的兼容。
JS兼容化文件
加载Ext4完毕后,你可选择加载这份兼容化文件。该文件的目的在于提供兼容Ext3的简写方式和覆盖新参数为适合旧版的参数。
注意: 此时此刻兼容化文件尚未释出可用,不过应该会在发布4.0正式版之前提供给大家。
沙箱模式
Ext 4完全基于沙箱设计的,因此可以让旧版的Ext与Ext4”同处一室“,在同一个浏览器运行时中做到兼容(译注:有一个桌面的例子,仍使用Ext3代码)。从JavaScript角度看,原来所有修改对象原型的方法已被转移,转移到全局对象Ext之下。现在只需要建立一个Ext对象的引用,分配不同的名称,就可以从以前旧版本的Ext中区分开来……
在标签markup/CSS方面,由于Ext4采用了Compass和SASS框架并通过模板生成CSS,所以很容易设定一个前缀,供CSS规则之用,比如Ext.baseCSSPrefix属性就是对应的前缀。结果,要与旧版Ext的CSS区分开来,也不是什么难事了。
包与命名空间的更新
在重构过程中,全体类和包的结构已经发生了变化。如何变化将是根据严格的命名转换来规范的,这一点对于重构的结果非常重要,以便于我们能更轻松地查找某一个类。例如Ext3的Button类、CycleButton类和SplitButto类就连同其他类归类在/widgets中。尽管不同层次的对象却也直接地命名在全局对象Ext身上。
在Ext 4,每一个类根据其特性的相似来决定其包的位置。虽然只是命名上的变化,但比起Ext3能更精确地描述对象。同样拿Button按钮为例子,Ext4的类这样分配:
单独设一个包src/button/
代码划分出一个新的命名空间
改名,如Ext.SplitButton→ Ext.button.Split
为了尽可能地照顾Ext3的旧命名方式,Ext4的类有一个特殊属性称作“alternateClassName”,通过这个属性就可以让Ext3遗留项目采用Ext4新的类库。例如alternateClassName: 'Ext.SplitButton'。当然,我们很希望你完全采用Ext4开发方式。
Ext Core
新型类系统
参考资源
Ext JS 4的倒数:动态加载和新的类机制(上)
Ext JS 4的倒数:动态加载和新的类机制(下)
Ext JS 4 的类机制主要围绕传统OO模型而设计,弥补了Prototype OO不足。虽然性质上仍为模拟的手段,但包含了比较完整的OO特征,并且保持对旧Ext3类机100%兼容。Ext JS 4(连同 Ext Core)提供的新功能有:
继承方面Ext.defined代替了原来Ext.extend的写法。
自动计算依赖关系及动态类加载。
多态
静态成员
为配置项自动生成的getter/setter方法
ext4-class-system.jpg
如何写类?
你仍可在Ext4使用new ClassName()的语法,不过推荐使用Ext.define()函数定义新类。利用Ext类系统显式定义好的类,将有什么不同呢?关键字new仍然可用,可没太大的特别。Ext.define还有一个好处,自动创所须的建命名空间,从而免去声明命名空间的一步。
这里是利用新语法定义的一个新Ext.Component子类。
// Ext 3:
Ext.ns('MyApp'); // 命名空间在Ext 3是必须的
MyApp.CustomerPanel = Ext.extend(Ext.Panel, {
// etc.
});
// Ext 4
Ext.define('MyApp.CustomerPanel', {
extend: 'Ext.panel.Panel',
// etc.
});
加载类
Ext 4终于引入了动态类加载的系统了,虽然你可以选择使用,也可以选择忽略,但无论怎么说,终于考虑这点,希望社区不再利用此缺点来指责Ext之庞大。首先交待一下提供哪些功能:
动态加载(Dynamic loading):运行时期间,Ext内部会根据依赖树的关系异步地下载类文件。这意味你不用再页面上手动引入include子类的HTML标签就可以加载你所需的资源,同样不会造成阻塞。开发期间,动态加载的灵活性远比关心页面加载速度的意义打得多。
动态生成build文件(Dynamic build generation):对于产品化,很希望就是打包为一份文件,亦即build files。由于Ext已经清楚掌握依赖关系,所以很容易导出一个依赖关系图,适合于某些自定义build配置。更开放的是,不限于Ext的命名空间,只要按照Ext类规范写类,Ext就会计算它们的关系。在不久的将来,Ext开发者会享用”一键化“的build服务,而且一切都是经过智能计算的,决没有冗余的代码。
动态加载必须有两个前提条件,一是打开Ext.define;二是在写类的时候须清楚指明依赖关系,当中关系所涉及两个属性说明如下:
requires: 所依赖的类。保证当前被实例化之前其他类就绪。
uses: 可选的依赖,不一定必须的(上面requires是指定必须的模块)。uses的类可以异步下载,不限于一定要在类实例化之前(因为异步的,可能之后)。
多态Mixins
多态(或译作“混元”)可以为现有的某个对象注入客制功能提供一种灵活的方式。mixins配置项,包括实例化类期间,允许给类原型“混入”新的能力。这与Ext.override函数作用类似。尽管该方法不会覆盖现有的方法,就像override那样不会直接覆盖,但是该方法的参数还是。Mixins语法如下:
Ext.define('Sample.Musician', {
extend: 'Sample.Person',
mixins: {
guitar: 'Sample.ability.CanPlayGuitar',
compose: 'Sample.ability.CanComposeSongs',
sing: 'Sample.ability.CanSing'
}
});
静态成员(Statics)
通过statics这个属性可以设置类的静态成员。
配置项 Config
Ext之中我们用术语“配置项(config items)”来表示任意的属性,这些属性在类原型(class prototype)都可以明确找到。有了配置项可以通过代码的调用对API读或者写。Ext 4在这点上基本没有什么问题,唯一作出新内容的便是带来了特定项“config”。当类定义中加入config属性,其对象所包含的内容指的就是“配置项”,而且强调一点就是,围绕配置项自动产生getter、setter、reset和apply方法,其中setter还提供模板方法自定义setter逻辑。基本示例代码如下:
Ext.define('MyClass', {
config: {
title: 'Default Title'
}
});
……根据以上介绍的机制,自动生成下列方法:
title: 'Default Title',
getTitle: function() {
return this.title;
},
resetTitle: function() {
this.setTitle('Default Title');
},
setTitle: function(newTitle) {
this.title = this.applyTitle(newTitle) || newTitle;
},
applyTitle: function(newTitle) {
// 自定义代码
// 如Ext.get('titleEl').update(newTitle);
}
Env命名空间
提供浏览器和操作的相关信息,还有告诉我们现代浏览器提供了什么功能。
Ext.env.Browser
该类提供了全部浏览器的元信息(名称、引擎、版本、是否Strict模式等等) ,用于全局对象Ext。
Ext.env.FeatureDetector
这是一个在Ext3中没有类,完全新的功能,其功能在于检测浏览器特性如何,主要针对现代HTML5和CSS3的特性,包括移动平台在内的特性列表,有:
CSS 变形、动画、转换
Canvas、SVG、VML
触控能力、方向
导航 Geolocation
SqlDatabase
Websockets
History
Audio
Video
Ext.env.OS
提供当前主机操作系统的信息(包括移动OS的列表)。
语言包(Lang Package)
同样的功能在Ext中都会有,但这是一个新的包,之所以定义为一个新的包,是为了尽量不会影响到JavaScript的对象原型。尽管在对象原型中设置方法会比较方便,但是如果引入了其他JavaScript一起,很难说会不会构成冲突或者影响的说。再者,如果日后ECMAScript规范作出了修订,会不会与Ext所定义的构成重叠呢?所以,要解决以上顾虑,我们还是把语言方法的命名空间定义在Ext对象之下,避免在对象原型身上定义的成员。
实际上虽然没有分配一个“lang”的这么一个命名空间,但是还是在源码树(Source Tree)中划分了一份文件专门定义语言增强函数。前后变化如下:
Array → Ext.Array
Date → Ext.Date
Function → Ext.Function
Number → Ext.Number
Object → Ext.Object
String → Ext.String
请注意在兼容化文件中,仍会对核心对象的原型挂载方法之引用。重申一下,要真正升级到Ext 4并摆脱Ext 3旧的调用方式,就必须移除兼容化文件,最后升级到新的命名空间形式。
Ext.Function
Ext 4的函数原型Function prototype改变后,怎么调用?最主要的一点就是命名上发生变化,如Function.createDelegate()和Function.createCallback()分别重命名为 Ext.Function.bind()和Ext.Function();Function.defer()变化为Ext.Function.defer()。由于使用频率较高,我们在Ext对象上添加了快捷访问方式,便是Ext.bind、Ext.pass和Ext.defer;其余的函数方法像createSequence()和createInterceptor()就取消了,但引入新方法createBuffered()和createThrottled(),可以看看有什么用途。
如下是一些语法糖说明前后之变化:
// Ext 3:
myFunction.createDelegate(this, [arg1, arg2]);
myFunction.defer(1000, this);
// Ext 4:
Ext.bind(myFunction, this, [arg1, arg2];
Ext.defer(myFunction, 1000, this);
Ext JS
参考资源
Intro to Ext 4 (video
Ext 4 Architecture (video)
通用问题
适配器(Adapters)
之前的各个Ext版本中都可以透过使用适配器(adpaters)的方式转换第三方的JavaScript库为我所用。Ext4的话就没这支歌仔唱了。改朝换代后,Ext JS应用程序的底层库唯一限定为Ext Core。不过我们依然可以继续让Ext Core与别的JS库共存于一个JS运行时(实际上这就是为什么一些JavaScript对象其原型的方法都被<a href="#lang">移至到Ext中</a>去的原因)。不同的就是Ext不依赖于其他JS的底层库了。
ARIA
为达到ARIA用户友好性的支持,而且是全面的支持,Ext对每一块组件都细心打造进而在这方面加强之。Ext.Component新设有ariaRole角色的配置项属性,默认是“presentation”(该角色仅表示为可见的并没有更高的含义,也没有用户交互的功能)。然后就让后面更高层次逻辑来覆盖它。例如,Ext.button.Button对ariaRole覆盖,标识为“button”,就表示这个是一个执行按钮语义的这么一个物件,这对屏幕阅读者(Screen Readers)非常有用。不论按钮外观上表现得如何,API在实际会在渲染按钮的过程中,对其标签中添加上一项HTML属性:role。总之,伴随着ARIA的增强,Ext于用户友好性(Accessibility)方面的提升大家应该是有目共睹的。
另一项ARIA重要的特性便是Ext.Component内建了aria-disabled支持。这一切都是自动进行的。当HTML标准属性aria-disabled激活的话,就会为屏幕阅读者(Screen readers)表示出某些功能化UI元素的激活状态。
Data
3.x的数据已经变化了不少,4.x继续重构并加入更多新的元素。但其中一点必须提到的,便是4.x的数据被设计成为能够与SenchaTouch共享的代码,也就说不论ExtJS或SenchaTouch使用同一套类库。有关这么方面的教程已经有不少了,这里我们就一些必要的背景内容和新特性作一番介绍。当然,如果尚未了解的读者还是建议你们阅读一下之前的教程或资讯:
参考资源
Proxies (blog post)
Ext JS 4的倒数:程序员预览
Ext JS 4 数据包的演示例子
客户端数据层的革新:引入ActiveRecord模式
概述
针对Ext 3的兼容化文件使得数据包得以连续可供Ext3使用。论变化最大者,有Store和Proxy和新引入的Model。Model实质便是Record的升级。
Store与数据格式无关,即不再存在JsonStore/XmlStore之分。其加载和保存数据都经过Proxy来执行,而Proxy的数据由来自于Reader或Writer是里。Store可执行客户端的多排序、动态过滤和动态分组,并与服务端同步亦可。
Proxy既可附加到Store也可直接附加到Model,附加到Model的好处就是省去了处理Store的步骤。可以在配置Readers和Writers时候配置Proxy,从而来解码或编码来自服务器的数据。
Model 也旧版的Record和相似,加入了关系、验证和更多的内涵。
另外,Ext JS 4 也可以将Model持久化到本地存储,利用全新的LocalStrorageProxy类就可以无缝地把数据保存的HTML5的本地存储。
Draw
Draw包是全新的包没有一点Ext旧的包袱。Draw包具备自定义的绘图能力,通过抽象Canvas、SVG与VML引擎特性就可以根据当前浏览器的运行时选择最佳的绘图方式。Ext 4的<a href="#charting">图表</a>就是依赖于这个Draw包,不但如此,Draw包还可以拓展至其他类型的图形绘制。主要特性如下:
基于HTML5 标准
渲染原语形状文本、图形、渐变
操控颜色、矩阵转换等等的类库
Ext.draw.DrawComponent
继承自Ext.Component
检测特性调优引擎
可自定义引擎调优顺序
可参与布局
通过Ext.draw.Sprite 内建块管理
抽象的绘制元素
常规化引擎API语法之间的差异
属性
事件支持(通过继承Observable)
变形(旋转、转换、缩放)
经由Ext.fx实现了动画
SpriteComposites
图表与图形化 Charting & Visualization
图表Chart不是好端端地用Flash做的吗?现在4.0却对Flash大声“say no”——回归网页标准的处理手法,要用Canvas/SVG/VML来做代替了Flash,命名空间就是Ext.draw.*。随着改进一些复杂的JS动画也成为可能。和Dojo一样终于有了属于自己的图形类库。虽然新图表可以顺利支持到IE6的浏览器,不过还是希望不要太冒进,能够继续使用3.x的Flash。图表引擎会自动选择适合当前浏览器的渲染引擎。无论采用哪一种的图表底层引擎,全体图表的函数都定义为同一种的API。这对用户开发至关重要。
参考资源
SenchaCon Overview (video)
SenchaCon Overview (slides)
working-with-charts.gif
Fx
Ext 3的Fx类提供了一组有用的元素特效效果(平滑、高亮、渐显等)。Ext 4基本上依旧不变,而且在简单的元素效果的基础之上,还有突破的发展,例如通过Animator类,可协调负责页面上同时运行的多段动画。再例如,无论调整大小还是定位都可以使用Fx”Target“类选择目标(全称Ext.fx.target.*),这为创建动态UI打开了许多新的方式方法。
Layout
参考资源
Ext 4 Layouts (video)
Ext 4 Layouts (slides
ComponentLayout
ComponentLayout是一种新型的布局方式,许多复杂的组件就采用这种布局(与之对应的为ContainerLayout,“ContainerLayout”——传统基于容器布局的新名字)来计算内置元素的大小尺寸,以响应resize的调用。Field字段组件的FieldLayout布局,关于labell控件和input元素控件的大小尺寸和定位都是来自于ComponentLayout的逻辑。
FormLayout
Ext 4已经没有这种FormLayout了。请参阅[#form-layout Layout]的Form部分内容以了解更多。
BorderLayout
Border layout在Ext4或者Ext3中都是毫无差别的(即完全兼容)。
Panel的头部Header现在可垂直方向布置了,也就是说折叠一个垂直方向的头部时可以选择在东面或者西面来折叠,旋转九十度也没有问题(乃益于Ext 4新的<a href="#draw">Draw包</a>)。Ext3中的头部实质乃元素而已,而Ext4的却特有一个已经成熟的Ext.panel.Header实例,并有若干的方法。你可以使用布局的新方法getPlacerHolder获取头部对象。当然,作为Container的子类,Panel自然拥有全体Container的方法。对于第一次显示的是闭合状态的布局,则不会渲染头部组件对象。
另一个细微的差别就是已经不再支持cmargins配置项了。如同展开的面板那样,Header容器现在是相同的边距(margins)。这使得创建布局的时候,不管组件闭合的状态还是展开的状态,看上去都更一致。
从更加灵活的布局和制定布局这两点角度出发,现在BorderLayuout内部可允许嵌套HBox和VBox方式的布局来创建边界管理(the bordered arrangement)。
Component
普通的组件,只有设置其floating:true的话便变为一个“浮动”组件,浮动于文档流(document flow)之上。变为浮动之后,可对组件进一步配置,可否拖动、可否调节高宽等问题都可以配置。甚至可以作为子项加入到别的容器中去,但就是只是浮动在其上面,不参与布局运算。
全体浮动组件均有一个由ZIndexManager提供的z轴索引z-index。ZIndexManager来自于Ext 3的Window Group。一般情况下,单例Ext.WindowsMgr管理器负责管理像Windows这类浮动的组件。调用窗体对象身上的show()方法会在对document中进行渲染并显示。除此之外,调用窗体的toFront()或者toBack()方法都会涉及ZIndexManager。
参与容器渲染的浮动组件,虽然是浮动的,但必定位于容器内。渲染的时候就会先获取ZIndexManager之引用,然后查找需要z-index管理的父级容器。一般而言,单例Ext.WindowMgr将会提供一切信息。不过如果浮动的组件是一个浮动容器的后代,如Window的话,那么这个Window会创建一个其专用的ZIndexManager实例,然后其下辖的浮动组件则会相对于这个Window的Z-index来进行管理。
现在Ext中可谓提出了新的形式,通过z-index作为凭据来管理浮动的容器,无论容器多复杂,都可以快速地控制,也避免了组件之间的冲突影响。例如一个例子,窗体中的combo下拉箱子就总是在那窗体上,不影响其他层。
Form
Layout
Ext 3时代我们FormPanel利用FormLayout来定位field标签,input控件,错误提示等等任务。但一个重要的消息就是Ext 4的FormLayout取消掉了,取而代之的将是新成员FieldLayout(为<a href="#component-layout">ComponentLayout</a>的一子类)。标准布局则统一管理基础服务而这个FieldLayout又专门为字段标签控件所服务,而样的结果,只要是标准布局,就可以变为具有表单特性的布局。总之就是希望灵活性方面来个大跃进。
尽管标准布局就可以包含表单了,但是仍提供一个表单面板FormPanel,其容器的布局默认是anchor。
FieldContainer
为管理表单布局,Ext引入了新的Ext.form.FieldContainer类。这不但是一个标准的Ext.Container类,而且还是在Ext.Container的基础上加入标签(label)控件和错误信息等的这些考虑要素。这些label和错误信息的配置方法则与Ext.form.Field的无异,都是同一套API。就像真实字段输入控件自动拉伸占据空白空间那样,容器下子组件都会自适应尺寸。这样,在表单中加入复杂的组件也可以美观地分组,并且让表单的字段控件对齐起来。
Field as Mixin
长久以来要为非Field组件加入字段式的能力如布局、数据验证、值管理等等是一道难题。最简单的方法就是直接继承于Ext.form.Field从而获取相应的能力。虽然简单可行,但却破坏了原组件的继承链。究其原因,在于Ext或JavaScript只能提供“单根继承方案”,无法直接实现多继承。当然这属于Ext3的困窘,于Ext4中这一切都将成为过去,通过提供多态<a href="#class-mixins">mixins</a>的支持,能够让我们告别旧有只是复制Fields对像到类原型(Class Prototype)的拙劣手段。
Field被设计为多态类,可混入到其他主类上,结果就是可让任意组件拥有Field API的全部能量。当然你也可以根据需求来修改Field的具体行为,例如重写getValue方法和setValue方法。
Validation
一个常见的场景便是对用户输入的数据马上进行有效性的检测。早在Ext 3就有表单验证了,前提是打开FormPanel的monitorValid选项。但是打开改选项后,每秒钟都对表单进行验证,所以显得十分的慢。
Ext 4不能容忍这点不足,所以重新设计过新的事件流如下:
输入框控件随时会侦听来自浏览器的事件,就是为检测内容有什么变化。用户一输入内容,即打字输入、剪贴、复制、拖动文本到输入框都会使得输入框内容发送变化。我们封装这些浏览器事件为changeevent事件以检测输入框的变化(下面会有详述这部分细节)。
一旦改变值,每个字段就会立刻对其自身进行验证。当字段的有效性从无效的有效性转变为有效的有效性之时,便会触发validitychange事件,反之亦然。
字段触发validitychange事件后,又会导致表单范围内的有效性检测,BasicForm触发其自身的validitychange事件。
新的事件流可以立刻向用户反馈用户的输入情况,之所以迅速是因为新事件的性能比过去轮询(polling)的机制快得多。故所以,事件流的方式将是默认的方式(Ext 3却不是,必须显式启用)。当然你也可以禁止事件流的方式。
然而存在某些特殊的情况,轮询的价值似乎值得重新考虑。一些浏览器(例如Opera和一些老版本的Safari)处于edit mode的时候(通过鼠标右键剪贴或粘贴时)总是不能触发检测事件。要解决这类问题,你可以打开FormPanel的pollForChanges参数以允许通过轮询检测字段的变化。触发器仍如上述事件流的一般。——不得不说轮询的做法性能上不好,但比起Ext 3轮询的强度则没那么严重,因为每次轮询只是对值的观察,而没有繁重的数据验证的参加(指值解析、转换和正则模式匹配等的验证)。
当检测到字段发生变化时,就会对字段内容进行数据验证(假设已打开validateOnChange)。检测内容变化的浏览器事件多种多样,都保存在checkChangeEvents参数中,我们可以访问该参数来获取该事件名称。根据浏览器的不同,可能出现的checkChangeEvents值有:
对于InternetExlorper而言checkChangeEvents为change和propertychange。
对于其他浏览器而言checkChangeEvents为change、input、textInput、keyup。
两点所列出的大体上包含可以检测到的用户输入变化的事件。几乎可以支持到全体可支持浏览器,然而,还是有一些情形不能检测变化,列出如下:
Safari 3.2或更老的版本:鼠标右键剪贴或粘贴,拖到文本到textareas。
Opera 10和11:拖到文本到输入框和textareas,鼠标右键剪贴输入框和textareas的内容。
Opera 9: 除了Opera 10 and 11提到的外,还有用鼠标右键粘贴输入框和textareas的内容。
(译注:Oprea的QA咋留着这么多bug……:))如果你必须要通过轮询才能检测到值发生变化的话,你可以打开FormPanel的配置项pollForChages和配置项pollInterval,或者设置一计时器不停调用startPolling()方法和stopPolling()方法都可以检测到。
Ext 3支持按钮的formBind属性,目的在于可以表单验证对在表单元素范围之外的按钮控制其enabled/disabled状态。Ext 4则不限定在表单验证,而是拓展至FormPanel中任意的组件。
FieldDefaults
旧Ext 3的FormLayout包办了全部字段的在表单怎么显示的问题,如hideLabels、labelAlign等等,都是FormPanel的配置项属性。由于Ext的表单容器采用标准布局,不存在FormLayout,要指定普通字段的布局属性的话,就要进入层层的容器或字段,将会十分复杂。故所以FormPanel特别提供一个fieldDefaults对象,指定的值供全体字段对象所使用,不论嵌套多少层的FormPanel。
BasicForm
Ext 3的BasicForm用途不是很广,只是在FormPanel内部偶尔用一下。Ext4的话BasicForm重新打造得更为灵活和易于扩展。新Basic不再需要一个容器以分配元素,也不需要其所在的容器手动通知BasicForm加入或删除字段。也就是说,它完全与FormPanel解耦,有条件在任意容易中发挥管理表单字段的能力。
数据表格(Grid)
这次升级Ext 4全部重写了Grid组件。显然,诸多理由和原因迫使我们升级Grid,但Ext 4 Grid向后兼容方面真的很难顾全。为此,我们将会提供一份关于Grid在Ext3升级到Ext4的指南。
智能化渲染
旧Ext JS 3 Grid工作起来还是蛮不错的。但透过“最小公分母(least common denominator)”的方法论来确定其各种功能的话,很容易带来一点不足的就是,伴随着Grid的每一项功能,都会生成大量的HTML Markup产生。我们不得不面对这个问题。于是在ExtJS 4中,规定Grid的每一项功能,只会根据开发人员设定与否,才会渲染出与之对应功能的Markup在页面上。Grid默认启动时只有为数不多的Markup而已。这样设计API的结果,便是在渲染页面以及Grid整体效能这双方面均得到极大的提升。
标准化布局
渲染流水线得到了改善,Grid的其他方面亦齐头迈进,不甘人后。许多Grid的部分都被规划成为单独、清晰的Component组件,整合到标准的布局管理系统中,并非旧版中直接处理内部Markup、CSS的那种方式。这使得API可以联合框架的其他强大的特性,进而来统一Grid的渲染流程。而这些过程,仍维持在精确到象素级别水准(pixel-perfect)的UI体验。
例如,新的HeaderContainer类就很能说明这个问题。Ext3中的列头部(Column headers)整合到Grid的话感觉是比较生硬的,因此不太容易客制化。Ext4的列头部作出改进,其所使用的HBox标准布局就能够让你在每一列上输入灵活的flex值。
扩展新功能
在Ext JS 3里面为Grid加入新功能,一般API接口方面有良好的考虑。但现在来看,却没有一种清晰的流程方法去指导,显得比较乱。有时通过写插件(Plugins),有时就写子类。总之扩展Grid的话可能会比较复杂。要解决上述问题,实质就是提供一种彻底灵活的选项操作。ExtJS 4将引入全新的一个Grid基类,称作Ext.grid.Feature。通过继承这个Feature类,对任何Grid其所在模板(Template)进行修改,就可以控制当前Grid视图生成的Markup结果。Features类跟旧版的GridView相似,但能力更强,也更为有用。之所以有用和强大,是在于其对延续Grid功能这点上表现得更为简单和适配。Grid里头的一些功能如RowWrap、RowBody和Grouping都是Fetures之子类。
Ext 4 grid相关功能的演示例子有如下:
RowWrap
RowBody
Grouping
Chunking/Buffering
虚拟滚动
Ext 4 Grid已经可以做到原生支持“按需加载(load-on-demand)”的数据视图了。虽然这是个虚拟视图,但是的确可以能够做到数据的缓冲。无论上百条抑或达上千笔的数据,都可以保证在Grid轻松显示。无疑,这将大大扩充了Grid数据处理能力。
编辑单元格控件
我们依然拿旧版对比一下。Ext 3里面要编辑Grid单元格,就必须制定EditorGrid类。通过继承方式可能不太灵活,于是Ext 4就否决了继承的方式,而是采用“插件化”的方式。通过Ext JS4的Editing插件可以自由绑定到任意的Grid的实例,对于全体任何类型的Grid均可使用。于是乎,此举又为提高“灵活性(flexibility)”添泼了一抹浓彩。此外,对于Ext 3中很受大家所欢迎的一款扩展:RowEditor,在这次发布我们也将RowEditor正式加入的Ext 4包中去,成为标准类库的一员。
DataView
GridView的父类更改为DataView。这样做的好处不仅减少了代码量,而且使得Grid更容易制定。因为可以直接发挥DataView的选区模型,应用到任意一种的视图,包括那些非连续的选区,例如通过键盘Home、End、PageDown和PageUp所产生的选区。
面板Panel
支持了边界接触(Docking)
Panel的改变之一便是通过面板特定的组件布局类(a panel-specific ComponentLayout)来负责管理其边界内所接触的元素项。面板body元素会铺张至任何空白的位置。任何组件都可以通过设置目标面板的dockedItems配置项属性来相接触,而且对方面板的dock属性也要与之设置好才行。如此一来,Ext3中困难重重的水平界工具条现今已大幅改进其灵活性,在Ext4中轻而易举地实现上述功能。
头部Header的改进
头部Header 现今为容器子类的第一类公民,从而获得子组件管理与布局的特性。你可以设定headerPosition的配置为 'top'、'right'、'bottom'或'left'的其中之一来决定和ader所依靠的位置(new docking support)。
Tool工具按钮(即像关闭、最小化此类的按钮)虽然在Ext3中都有,不过现在是属于Component的子类了,显得更灵活。
Resizer
Ext很早就有调节大小的控件,但只为DOM元素服务。现在Ext 4任意组件也可以透过Ext.resizer.Resizer达成调节大小的一方面功能。这对浮动的组件比较有用,或者说没在Ext容器体系以外渲染组件的时候,将会派上用场。
只要设置组件resizable:true的配置项,那么将会分配多个调节手柄到组件的边界上。默认用一个代理元素来产生调节大小的效果,mouse up之后就会真正让组件的大小进行变化。具体的调节行为可以通过修改配置项对象resizable,——这个对象便是Resizer类的参数对象。
ComponentDragger
Ext一向支持多种方式的拖放支持,不过尚在DOM元素的级别。Ext 4改进后,新引入的Ext.util.ComponentDragger提升到组件级别,使得组件的拖动更简单。ComponentDragger对浮动组件比较有用,对非容器模型的UI控件也是有的。
只要设置组件的配置项draggable:true,这个组件就可以通过鼠标来拖动了。Windows本身就是可拖动的。拖动期间,被拖动的dragger实际是一个空白的“幽灵”,鼠标松开后,面板或窗体移动到目的地位置,然后这个“幽灵”也会消失。指定draggable的配置项可以修改dragger行为,该配置对象同样适用于ComponentDragger的配置对象。
分割栏 Splitter
箱子布局HBox和VBox都可以包含Ext.resizer.Splitter组件,用于调整箱子之间的尺寸。最小和最大的尺寸都可以支持的。默认下,对箱子布局其中一个flex项进行调整大小的话,就会把原来的flex的值变为精确的像素值,flex值将会删除。如果不想这种情况出现,可以配置maintainFlex:true就可以保持flex值,哪怕在调整大小操作之后。但这只适用于分割栏划分两块中的其中一块。
TabPanel
与其他众多Ext的组件一样,组成一个TabPanel的主要部分,已被分解并成为Ext4组件之第一公民。Tab本身在Ext3只是若干DOM元素,现在Ext4中却是重新认识Tab为一个”按钮“,容纳这些Tab的容器则就是一个容器。各方面显示,4.x的TabPanel比起Ext3提升的灵活性是显著的。
以上的做法,就是从包含内容的子面包中分离出来这些tabs,形成不同的小组件。正因为这样的分离,我们现在可以允许了tab面板中显示标题titile、工具按钮等在旧Ext3中无法想象的功能特性。
工具条 Toolbar
Toolbar现在为容器之第一公民了,加入新组件或自定义Toolbar布局的话,比起Ext3来得更加容易。
主题(Theming)
承蒙厚爱,Ext之主题一向被认为出彩的地方,看起来很好,可修改起来却不容易。虽然Ext 3通过分离结构以及可视化样式表改善了主题制定任务,但是尚不足够,仍有冗余、繁杂的浏览器私有特性以及一个关键,便是CSS本身语言不足所带来的问题。
参考资源
Ext 4 Theming (video)
Ext 4 Theming (slides)
Compass与SASS
Ext的主题样式借助了新工具来实现的,内部透过转换Compass和SASS来作为主要CSS输出工具。SASS为CSS标准的超级,加入了许多新的高级功能。
内嵌选择器
变量
多态
选择器的继承
编译和压缩
哪些组件需要的样式就导出,不需要的样式就不导出
Markup的不同
Ext现在支持了特定版本或浏览器的组件markup,比起Ext3跨越了一大步。
文档
支持类更多的新元素(requires、mixins等)
支持遗留项元素
记录浏览历史
内涵例子、视频等
关注话题
多框架和版本的支持
本地搜寻