Ext 4 Layouts (video)
Ext 4 Layouts (slides
ComponentLayout是一种新型的布局方式,许多复杂的组件就采用这种布局(与之对应的为ContainerLayout,“ContainerLayout”——传统基于容器布局的新名字)来计算内置元素的大小尺寸,以响应resize的调用。Field字段组件的FieldLayout布局,关于labell控件和input元素控件的大小尺寸和定位都是来自于ComponentLayout的逻辑。
Ext 4已经没有这种FormLayout了。请参阅[#form-layout Layout]的Form部分内容以了解更多。
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)。
普通的组件,只有设置其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下拉箱子就总是在那窗体上,不影响其他层。
Ext 3时代我们FormPanel利用FormLayout来定位field标签,input控件,错误提示等等任务。但一个重要的消息就是Ext 4的FormLayout取消掉了,取而代之的将是新成员FieldLayout(为<a href="#component-layout">ComponentLayout</a>的一子类)。标准布局则统一管理基础服务而这个FieldLayout又专门为字段标签控件所服务,而样的结果,只要是标准布局,就可以变为具有表单特性的布局。总之就是希望灵活性方面来个大跃进。
尽管标准布局就可以包含表单了,但是仍提供一个表单面板FormPanel,其容器的布局默认是anchor。
为管理表单布局,Ext引入了新的Ext.form.FieldContainer类。这不但是一个标准的Ext.Container类,而且还是在Ext.Container的基础上加入标签(label)控件和错误信息等的这些考虑要素。这些label和错误信息的配置方法则与Ext.form.Field的无异,都是同一套API。就像真实字段输入控件自动拉伸占据空白空间那样,容器下子组件都会自适应尺寸。这样,在表单中加入复杂的组件也可以美观地分组,并且让表单的字段控件对齐起来。
长久以来要为非Field组件加入字段式的能力如布局、数据验证、值管理等等是一道难题。最简单的方法就是直接继承于Ext.form.Field从而获取相应的能力。虽然简单可行,但却破坏了原组件的继承链。究其原因,在于Ext或JavaScript只能提供“单根继承方案”,无法直接实现多继承。当然这属于Ext3的困窘,于Ext4中这一切都将成为过去,通过提供多态<a href="#class-mixins">mixins</a>的支持,能够让我们告别旧有只是复制Fields对像到类原型(Class Prototype)的拙劣手段。
Field被设计为多态类,可混入到其他主类上,结果就是可让任意组件拥有Field API的全部能量。当然你也可以根据需求来修改Field的具体行为,例如重写getValue方法和setValue方法。
一个常见的场景便是对用户输入的数据马上进行有效性的检测。早在Ext 3就有表单验证了,前提是打开FormPanel的monitorValid选项。但是打开改选项后,每秒钟都对表单进行验证,所以显得十分的慢。
Ext 4不能容忍这点不足,所以重新设计过新的事件流如下:
新的事件流可以立刻向用户反馈用户的输入情况,之所以迅速是因为新事件的性能比过去轮询(polling)的机制快得多。故所以,事件流的方式将是默认的方式(Ext 3却不是,必须显式启用)。当然你也可以禁止事件流的方式。
然而存在某些特殊的情况,轮询的价值似乎值得重新考虑。一些浏览器(例如Opera和一些老版本的Safari)处于edit mode的时候(通过鼠标右键剪贴或粘贴时)总是不能触发检测事件。要解决这类问题,你可以打开FormPanel的pollForChanges参数以允许通过轮询检测字段的变化。触发器仍如上述事件流的一般。——不得不说轮询的做法性能上不好,但比起Ext 3轮询的强度则没那么严重,因为每次轮询只是对值的观察,而没有繁重的数据验证的参加(指值解析、转换和正则模式匹配等的验证)。
当检测到字段发生变化时,就会对字段内容进行数据验证(假设已打开validateOnChange)。检测内容变化的浏览器事件多种多样,都保存在checkChangeEvents参数中,我们可以访问该参数来获取该事件名称。根据浏览器的不同,可能出现的checkChangeEvents值有:
两点所列出的大体上包含可以检测到的用户输入变化的事件。几乎可以支持到全体可支持浏览器,然而,还是有一些情形不能检测变化,列出如下:
(译注:Oprea的QA咋留着这么多bug……:))如果你必须要通过轮询才能检测到值发生变化的话,你可以打开FormPanel的配置项pollForChages和配置项pollInterval,或者设置一计时器不停调用startPolling()方法和stopPolling()方法都可以检测到。
Ext 3支持按钮的formBind属性,目的在于可以表单验证对在表单元素范围之外的按钮控制其enabled/disabled状态。Ext 4则不限定在表单验证,而是拓展至FormPanel中任意的组件。
旧Ext 3的FormLayout包办了全部字段的在表单怎么显示的问题,如hideLabels、labelAlign等等,都是FormPanel的配置项属性。由于Ext的表单容器采用标准布局,不存在FormLayout,要指定普通字段的布局属性的话,就要进入层层的容器或字段,将会十分复杂。故所以FormPanel特别提供一个fieldDefaults对象,指定的值供全体字段对象所使用,不论嵌套多少层的FormPanel。
Ext 3的BasicForm用途不是很广,只是在FormPanel内部偶尔用一下。Ext4的话BasicForm重新打造得更为灵活和易于扩展。新Basic不再需要一个容器以分配元素,也不需要其所在的容器手动通知BasicForm加入或删除字段。也就是说,它完全与FormPanel解耦,有条件在任意容易中发挥管理表单字段的能力。