ExtJS 4 布局和容器:Layouts、Containers

布局系统,是 Ext JS 中功能最强大的部分之一。系统中的每一个组件在页面上的尺寸和位置,都由该部分负责管理。这篇文档是 Ext JS 布局入门的文档。

Containers

ExtJS 的图形界面,是由组件构成的。容器,是一种特殊的组件,其功能就是包含其他组件。一个典型的 ExtJS 应用由若干层嵌套的组件构成。

最常用容器类组件是 Panel。下面的代码展示了 Panel 作为一个容器如何包含其他的组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 400,
height: 300,
title: 'Container Panel',
items: [
{
xtype: 'panel',
title: 'Child Panel 1',
height: 100,
width: '75%'
},
{
xtype: 'panel',
title: 'Child Panel 2',
height: 100,
width: '75%'
}
]
});

上面的代码创建了一个 Panel,在 HTML 的 Body 元素上渲染,里面添加了两个子面板。

Layouts

每个容器类的组件都有一个布局用来管理其内部组件的尺寸和位置。这里,我们要展示一下一个容器如何通过配置来使用某种特定的布局,并且看看布局系统如何保证每个部分都同步。

使用布局

在上面的例子里,我们没有制定最外层 Panel 的布局,所以内部子 Panel 就是一个挨着一个,从上到下顺次排列在外层的 Panel 上面。其布局形式跟一般的 Html 块级元素在页面呈现的布局相似。这在 ExtJS 中,也是一种布局方式,叫做 Auto Layout,该种布局方法,不指定任何子组件的位置和尺寸。假如,我们需要两个子 Panel 并排排列,各占 50%的宽度,我们可以使用 Column Layout 列布局,只要通过指定容器的 layout 属性,就可以做到这一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 400,
height: 200,
title: 'Container Panel',
layout: 'column',
items: [
{
xtype: 'panel',
title: 'Child Panel 1',
height: 100,
columnWidth: 0.5
},
{
xtype: 'panel',
title: 'Child Panel 2',
height: 100,
columnWidth: 0.5
}
]
});

ExtJs 有全系列的布局方案,可以实现几乎任何你能想象出来的布局。

布局系统的工作原理

一个容器的布局负责初始化所有子组件的位置和属性。框架内部会调用容器的 doLayout 方法,这会触发 Layout 来计算出所有子组件正确的尺寸和位置,并且更新到 DOM。doLayout 方法是递归调用的,所以,所有子组件的 doLayout 方法,也会在那个时候被调用,一直到最底层级的组件为止。你在使用框架的时候,没有必要自己手动调用 doLayout,框架会为你做好这个工作。

当容器被 resize 的时候,会触发容器的 re-layout,或者子组件内部的对象被添加或者删除的时候也会触发这个过程。通常情况下,我们只要依赖 framework 提供的功能来处理布局更新的事宜,但是有些时候,我们可能希望框架不要替我们做这件事情,因为我们可能需要连续操作若干的组件,我们会希望等所有操作完成后,一并重新计算布局信息。这个时候,我们可以用容器的 suspendLayout 标志来阻止自动的 layout,当我们处理完容器内部的组件后,我们要做的工作是取消 suspendLayout,然后手动调用 doLayout 方法。

组件布局

就像容器有布局一样,组件也可以通过指定布局来管理位于其上的控件和对象。组件布局使用 componentLayout 属性来指定。一般情况下,你是不需要指定这个属性的,除非你在自定义组件,因为所有的预定义组件都已经带有了他们各自的布局管理器来里管理位于其内部的元素尺寸和位置。大部分组件使用 Auto Layout,但是复杂的组件需要一个自定义的组件布局,比如 Panel。

Layout 盘点

ExtJS 4 Layout

从这个图里面,我们可以看到组件布局中,只有一种布局就是 Auto,而大部分布局都是在容器布局下面。下面逐一来罗列一下这些布局的用途:

布局用途
Anchor使包含的元素相对于容器的尺寸发生变化。如果容器被 resize,那么内部包含的元素就会根据指定的规则来自动重绘。这种布局一般不使用 new 来创建,也没有直接的配置选项。此种布局没有任何直接的配置选项。缺省情况下,AnchorLayout 基于应用容器的尺寸来计算锚定规则。使用 AnchorLayout 的容器,可以通过 anchorSize 属性来设定可供内含组建计算尺寸用的虚拟容器。(经我实际在 Panel 上测试,该属性不起作用,不知道什么原因)
Absolute是 AnchorLayout 的子类,在 Anchor 的基础上,提供了通过 x、y 的值来指定内含组建位置的能力。
Box不能直接使用,是 HBox 和 VBox 的基类。
VBox在容器中,垂直布局内含组建的布局。这个布局将垂直方向上的空间,按照 flex 属性指定的值分配给内含组件,作为其高度。可以设置内含组件的宽度 width 和水平对齐属性 align。flex 相当于是按照比例分配高度的意思。比如可以通过 flex 属性,将内含三个组件的高度设为 2:3:3,它们会按照这个比例,占满容器的高度。将 flex 设定为 0 或者 undefined,组件的高度将不会变化。
HBox水平排布内部组件的容器布局方式。同 VBox,也有个 flex 属性,行为相同。
AccordionVBox 的子类,实现了一种让许多面板在垂直方向上可以折叠展开的布局方式。任意时刻,只能展开一个面板。折叠和展开的行为都是自动支持的,不需要额外的编程。只有 Panel 和 Panel 的子类才能用于使用了 Accordion 布局的容器内部子组件。
Auto这是一个缺省布局方式,如果一个容器没有指定 layout 的话,都会使用 Auto 布局方式。Auto 布局什么都不做,只是把布局的调用透传给子容器。
Form这种布局方式用于渲染表单域,表单域一个一个纵向排列并且会被拉长到填满容器的宽度。在这种布局内,内部元素上设定的 padding 值都会被忽略。
Border这是一种多窗口,面向应用的 UI 布局样式。支持多层嵌套面板,块于块之间自动的分界,支持某块区域的展开和缩起。通过 border 关键字来指定或者扩展,一般不用 new 关键字来创建。此布局内的空间被分为东南西北中五个区域。设定 split 属性为 true,可以使某块区域能被 resize。所有使用这种布局的容器,至少要指定一个子元素,来占据“中间”区域 center。中间区域的子组件总是会撑满容器没有被设定的剩下区域。西侧或者东侧的子组件可以指定初始宽度,或者通过 flex 属性来指定宽度占比。同理,南北两侧的可以指定高度。可以用 collapsible 设定是否可以折叠。
Fit对于只包含了一个组件的容器,这种布局使得内部组件撑满容器。这个布局没有配置选项。如果容器中有多个组件,所有的组件的尺寸都会设为相同,这一般来说都不是我们期望的行为,所以在 fit 布局的容器中,只能放一个子组件。
Card这种布局形式,将容器内部子组件都撑满到容器的大小叠放,所以一次只能显示位于最上面的那个组件。这个布局方式,通常用来创建应用的向导程序。这种布局有个方法 setActiveItem 来决定显示哪个组件,参数是 id 或者下标。布局本身不提供 UI 来实现内部组件的导航,所以开发向导的时候,要自己开发导航按钮。
CheckboxGroup这个布局用于实现复选框和单选框在页面上的布局管理。它根据组件的 columns 属性值和子组件的 vertical 属性值来组织布局容器内的元素。
Column对容器进行分栏布局,分栏的宽度可以用百分比,也可以用固定宽度。分栏的高度是可以根据内容来指定的。此布局本身没有什么配置选项,但是位于此布局中的面板,可以使用 columnWidth 属性来指定分栏宽度。在指定宽度的时候 width 属性和 columnWidth 属性都是有效的,width 的值必须是大于 1 的整数,columnWidth 的值是百分比,取值范围是 0 到 1 的左开右闭区间。在渲染布局的时候,外层容器首先遍历内部宽度固定的面板,然后算出剩余没有分配的宽度,然后按照 columnWidth 所指定的百分比,分给其他面板。所以,此布局中所有使用 columnWidht 指定宽度的面板的 columnWidth 值之和必须是 1,否则该布局的行为不可预期。
Table使界面按照 HTML 的 table 的形式来进行布局,可以指定总的列数,然后配合 colspan 和 rowspan 来生成复杂的表格结构。这个布局背后的思想就是一个 table 元素,所以,所有的注意点都跟 table 的注意点一样。该布局只需要指定列数 column,然后会将其内子元素按照从左到右,从上到下的顺序排布在界面上。

总结

ExtJS 4 给我们提供了丰富的界面布局,帮助我们能够快速简单的创建用户界面。