布局和容器

布局系统是 Ext JS 的最强大的部分之一. 它控制了应用程序中的每个组件的大小和位置. 本指南包含布局入门的基础知识.

容器(Containers)

Ext JS 应用程序界面是由一个个组件(Component)构成的 (更多关于 Component 的内容请看 Components 指南). 容器(Containers) 是可以容纳其他组件的一个特殊组件. 通常一个 Ext JS 应用程序就是由多层组件嵌套构成的.

最常用的容器是面板(Panel). 让我们看看 Panel 这个容器是如何容纳其他组件的:

代码编辑器 预览 在Fiddle打开
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%'
        }
    ]
});

我们创建了一个渲染到HTML文档的 body 中的 Panel, 我们用了 items 这个配置项将2个子 Panel 控件添加到我们这个 Panel 容器中.

布局(Layouts)

每一个 container都有layout ,用来控制它的子组件的大小和位置. 这里我们来讨论如何配置容器去使用一个特定类型的布局(Layout), 并且布局系统是如何让所有内容同步一致的.

使用布局(Layouts)

上面的例子中我们没有给 Panel容器指定布局. 注意,子 Panels 是一个接着一个布局的, 就像 DOM 结构中的元素块一样. 这是因为所有 Containers 默认的布局都是 自动布局(Auto Layout). 自动布局不为子元素指定任何特定大小和位置. 我们假设, 比如我们希望两个子 Panels 并排定位, 各个子 Panel 的宽度占父容器的一半 - 我们可以给 Container 的layout 配置为 列布局(Column Layout):

代码编辑器 预览 在Fiddle打开
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
        }
    ]
});

Ext JS 的全套布局不但简单易用,而且数量众多,几乎囊括所有类型的布局. 请看 Kitchen Sink 示例的布局部分 比较各种不同布局之间的差异.

布局系统的原理

A 容器(Container)布局(Layout) 主要负责其中子控件的大小和位置. 框架内部调用 Container 的updateLayout 函数来触发布局重新计算子控件的大小和位置,然后更新到 DOM 元素上. updateLayout 函数是递归的, 所以子控件也会调用自身的updateLayout 函数来重新调整自己的布局. 直到组件嵌套结构树的最底层. 基本上你不需要手动调用 updateLayout()因为框架会帮你处理的.

重新布局发生在 Container 改变了大小之后(resized), 或者当 Container 又添加移除子控件(items)的时候. 通常我们只要依赖框架给我们处理就行了, 但是有时候我们又需要组织框架自动为我们重新布局,以便我们可以批量操作界面,然后手动触发更新布局. 为了达到这个目的,我们设置 Container 的suspendLayout 属性为 true 来阻止框架自动更新布局 (比如添加或移除子控件). 当我们完成操作的时候要把 suspendLayout 属性设为 false,然后手动调用 Container 的updateLayout函数来触发布局更新

代码编辑器 预览 在Fiddle打开
var containerPanel = Ext.create('Ext.panel.Panel', {
    renderTo: Ext.getBody(),
    width: 400,
    height: 200,
    title: 'Container Panel',
    layout: 'column',
    suspendLayout: true // 阻止自动更新布局,因为我们要做的有些事情可能会触发自动更新
});

// 增加一些子控件.  虽然我们可以传递一个子控件数组给 add() 函数,
// 但是这里我们假设我们因为某些原因需要一个个添加.

containerPanel.add({
    xtype: 'panel',
    title: 'Child Panel 1',
    height: 100,
    columnWidth: 0.5
});

containerPanel.add({
    xtype: 'panel',
    title: 'Child Panel 2',
    height: 100,
    columnWidth: 0.5
});

// 开启自动更新布局.
containerPanel.suspendLayout = false;
// 触发布局更新.
containerPanel.updateLayout();

组件自身的布局(Component Layout)

就像 Container布局(Layout) 定义了 Container 的组件(Component)的大小和位置, 组件(Component) 自身也有一个布局(Layout) ,定义了它内部元素的大小和位置. 组件布局(Component Layout) 用的是 componentLayout 这个配置项.

通常, 你不应该使用这个配置项,除非你要写一个自定义组件,因为所有的组件都有自己的布局管理器. 大部分组件使用 自动布局(Auto Layout), 但是更复杂一些的组件自定义组件布局 (比如面板(Panel) 有标题栏(header), 底栏(footer), 和工具栏(toolbar)).

Last updated