原文链接:http://docs.sencha.com/ext-js/4-1/#!/guide/layouts_and_containers
布局系统是ExtJS中最为强大的部分之一。它用于处理你的应用中所有组件的大小和位置。这个指南通过介绍若干基本概念,来告诉你怎么样开始编写布局。
容器
一个Ext JS应用的UI由若干组件(Component)组成,容器(Container)是组件的一个具体的类型,他可以包含其他组件。一个典型的Ext JS应用是由许多层嵌套的组件组成:
最常用的容器是面板(Panel)。让我们来看看如何在面板的基础上创建子组件。
1 Ext.create('Ext.panel.Panel', { 2 renderTo: Ext.getBody(), 3 width: 400, 4 height: 300, 5 title: 'Container Panel', 6 items: [ 7 { 8 xtype: 'panel', 9 title: 'Child Panel 1', 10 height: 100, 11 width: '75%' 12 }, 13 { 14 xtype: 'panel', 15 title: 'Child Panel 2', 16 height: 100, 17 width: '75%' 18 } 19 ] 20 });
我们刚刚在body元素下创建了一个面板,然后通过配置(items)给面板容器加上了两个子面板。
布局
每一个容器都拥有一个布局对象来管理子组件的大小和位置。在下面的这个部分中,我们详述一下怎么给容器配置一个特殊的布局对象,还有,布局系统是怎么使得一切保持同步的。
使用布局
在上面的例子中我们没有给面板容器采用一个特定的布局。你若观察一下这两个子面板是如何一个接一个地摆放的(代码的具体运行效果见原链接,ps:可以在原链接中修改代码再运行),便不难发现他的布局方式和普通的block元素在DOM中的表现一致。这是因为所有容器的默认的布局方式是自动布局(Auto Layout)。自动布局没有对子组件的大小和宽度做任何的变动。接下来,我们来实现一个布局,我们想让两个子面板并排的排在一行,并且每个子面板各占父容器的50%的宽度。我们可以简单地使用列布局(Column Layout),给容器加上一个layout配置即可:
1 Ext.create('Ext.panel.Panel', { 2 renderTo: Ext.getBody(), 3 width: 400, 4 height: 200, 5 title: 'Container Panel', 6 layout: 'column', 7 items: [ 8 { 9 xtype: 'panel', 10 title: 'Child Panel 1', 11 height: 100, 12 columnWidth: 0.5 13 }, 14 { 15 xtype: 'panel', 16 title: 'Child Panel 2', 17 height: 100, 18 columnWidth: 0.5 19 } 20 ] 21 });
除此之外,Ext JS还提供了一系列的布局方式来满足任何你能想到的布局效果。可以查看一下Layout Browser,以便了解哪些布局效果是可行的。
布局系统是怎么工作的
一个容器的布局属性负责初始化该容器的所有子组件的大小和位置。框架内部是调用容器的doLayout方法来触发布局计算,计算得出容器的所有子组件大小和位置信息,并设置到相应的DOM上。doLayout方法是递归调用的,所以该容器的任何子容器的doLayout方法也会被调用。直到达到位于层级底部的子组件,才会停止继续的往下递归调用。一般情况下,在应用中你都不需要自己的调用doLayout方法,框架会帮你自动进行布局的计算。
当容器的大小变化,或容器新增或移除子组件时,会触发容器的重新布局(re-layout)。普通情况下,框架会处理好这个重新布局的过程。但是,当我们想批量的进行会触发重新布局的相关操作时,我们会需要阻止让框架自动的进行布局计算(优化性能)。这就需要我们设置suspendLayout标志为true,所有操作完毕后自己再调用一下doLayout方法:
1 var containerPanel = Ext.create('Ext.panel.Panel', { 2 renderTo: Ext.getBody(), 3 width: 400, 4 height: 200, 5 title: 'Container Panel', 6 layout: 'column', 7 suspendLayout: true // Suspend automatic layouts while we do several different things that could trigger a layout on their own 8 }); 9 // Add a couple of child items. We could add these both at the same time by passing an array to add(), 10 // but lets pretend we needed to add them separately for some reason. 11 containerPanel.add({ 12 xtype: 'panel', 13 title: 'Child Panel 1', 14 height: 100, 15 columnWidth: 0.5 16 }); 17 containerPanel.add({ 18 xtype: 'panel', 19 title: 'Child Panel 2', 20 height: 100, 21 columnWidth: 0.5 22 }); 23 // Turn the suspendLayout flag off. 24 containerPanel.suspendLayout = false; 25 // Trigger a layout. 26 containerPanel.doLayout();
组件的布局
容器的布局用来决定其子组件的大小和位置,组件的布局也和他类似,用来决定组件的子项(items)的大小和位置。组件的布局需要配置componentLayout属性。所有已提供的组件都会依据其布局方式计算出其内部DOM元素大小和位置信息,一般情况下,你不需要使用这个配置,除非你需要写一个自定义组件。大多数的组件都使用的自动布局,有一些复杂的组件会需要一些自定义的组件布局方式,例如一个有头部、尾部和工具栏的Panel。