Ext JS Layout 学习笔记

Ext JS 2.2 Samples 学习笔记

从直观的布局入手

例子目录:ext-2.2/examples/layout/

按照复杂程度依次学习:Anchor, Table, Accordion, Column, Complex

Anchor

首先挑出anchor.html主要部分如下:(所要关注的重点部分做了标记)

<script type=”text/javascript”>

Ext.onReady(function() {

var viewport = new Ext.Viewport({

layout:’anchor’,

anchorSize: {width:800, height:600},

items:[{

title:'Item 1',

html:'wtf',

width:800,

anchor:'right 20%'

},{

title:'Item 2',

html:'wtf',

width:300,

anchor:'50% 30%'

},{

title:'Item 3',

html:'wtf',

width:600,

anchor:'-100 50%'

}]

});

});

</script>

Ext.onReadyExt.EventManager.onDocumentReady的简写形式;API文档中定义如下:

onDocumentReady( Function fn, [Object scope], [boolean options] ) : void

Fires when the document is ready (before onload and before images are loaded). Can be accessed shorthanded as Ext.onReady().

本例中后两个参数都省略了,在此也不作考虑;fn传入了一个匿名函数。

Ext.Viewport是在浏览器视口内展现可见的应用程序区域的特定容器。Viewport会自动渲染自身,自动适应窗口大小并处理窗口大小的改变。在一个页面中只能有一个Viewport。事实上页面中的所有可视化元素最终都通过继承链将自身与Viewport关联并得到渲染。Viewport不处理也不支持Scrolling,因此如果需要,子面板必须提供对Scrolling的支持。

Viewportlayout指定使用的layout类型,默认使用Ext.layout.ContainerLayout。可以使用的值有:absolute, accordion, anchor, border, card, column, fit, form, table。由此可见我们需要学习的五个例子包含于其中。

anchorSize来自Ext.layout.AnchorLayout,指定了一个虚拟的容器大小。前后两个参数默认是配置水平和竖直方向的。而items中出现的anchor也是这样的。anchorSize属性可以有三种参数类型:百分比、偏移量、方向。百分比指定占用容器的大小。偏移量则会加在容器尺寸上。方向指定所靠的方向。三种类型的参数可以混合使用。

Items中出现的width没有搞明白是干什么的。如果把那三行注释掉,也没有什么影响。anchor属性决定了布局的尺寸。Item 1在水平方向上紧靠右边界,竖直方向上占窗口的20%Item 2在水平方向上占窗口的50%,竖直方向上占窗口的30%Item 3在水平方向上比窗口横向短100,竖直方向上站窗口的50%。浏览器中观察的结果也是这样的,看来对anchor描述的理解基本上应该是正确的。

extjs-01

现在来关注一下我们这样写的基础是什么。我们需要引用Ext JS的文件。ext-2.2/根目录下有文件INCLUDE_ORDER.txt,我们目前只是用了列出的第一种情况:Ext Stand-alone,引用顺序是:

<script type=”text/javascript” src=”adapter/ext/ext-base.js”></script>

<script type=”text/javascript” src=”ext-all.js”></script>

另外为了让样式正常显示,我们需要引用配置好的css

<link rel=”stylesheet” type=”text/css” href=”resources/css/ext-all.css”/>

打开ext-2.2目录就可以明白相对目录关系,在应用的时候不要忘记更改。

好了,现在我们不妨自己使用anchor来试验一下。我们建立自己的工作目录并把需要的文件拷贝过去,这样不会破坏既有的ext-2.2的结构。在这里我先拷贝了adapter/目录、resources/目录、ext-all.jsext-core.js

按照一个非常随意的想法,我写了下面的代码。注意为了简便,我根本没有考虑写法的规范性,这里只是为了做个试验,应用时一定不要这样写!

<link rel=”stylesheet” type=”text/css” href=”ext/resources/css/ext-all.css”/>

<script type=”text/javascript” src=”ext/adapter/ext/ext-base.js”></script>

<script type=”text/javascript” src=”ext/ext-all.js”></script>

<script type=”text/javascript”>

Ext.onReady(function(){

var viewport = new Ext.Viewport({

layout:’anchor’,

items:[{

title:'Anchor Item 1',

anchor:'20% 50%'

},{

title:'Anchor Item 2',

anchor:'30% 30%'

},{

title:'Anchor Item 3',

anchor:'50% 20%'

}]

});

});

</script>

Firefox中运行的结果如下:

extjs-02

看来我们的学习是成功的,程序运行得到了我们预想的结果。下面来学习Table

Table

首先还是先来看代码:(注意把内嵌样式表也包含进来了,主要是为了那个padding

<style type=”text/css”>

html, body {

font: normal 11px verdana;

}

#main-panel td {

padding:5px;

}

</style>

<script type=”text/javascript”>

Ext.onReady(function() {

var panel = new Ext.Panel({

id:’main-panel’,

baseCls:’x-plain’,

renderTo: Ext.getBody(),

layout:’table’,

layoutConfig: {columns:3},

// applied to child components

defaults: {frame:true, width:200, height: 200},

items:[{

title:'Item 1'

},{

title:'Item 2'

},{

title:'Item 3'

},{

title:'Item 4',

width:410,

colspan:2

},{

title:'Item 5'

},{

title:'Item 6'

},{

title:'Item 7',

width:410,

colspan:2

},{

title:'Item 8'

}]

});

});

</script>

我们先不着急去翻文档,而是直观地来看一下运行的结果:(右侧有很多空白割掉了)

extjs-03

显然这跟正常的HTML中的表格是差不多的:指定有多少列,然后一行行的排开(这一点要容易一些),还可以用colspan指定单元格跨度。但它不是单纯的单元格,只是表格化的结构,能表达更丰富的东西。

我做黄色标记的那个main_panel就是控制单元格之间间距的关键。如果把那个样式注释掉,会发现单元格挤在了一起,很难看的(所以就不截图了)。这样我们可以显然看到id属性的作用了。

那么现在我们来看Ext.Panel和它的三个属性baseClsrenderTodefaults

文档中对Ext.Panel的描述大概翻译如下:

面 板是含有特定功能和结构的组件的容器,这使得它成为构建面向应用程序的用户界面的绝佳选择。面板包括了底部和顶部的工具条以及头部、尾部和主体部分的区 域。它还提供了内置的伸缩行为特性以及其他很多的可以自定义的行为特性。面板可以很容易的放置在容器或者是布局中,并且布局和渲染管线是完全由框架管理 的。

从这段描述我们大致能明白Panel的作用了。baseCls则被描述为:

The base CSS class to apply to this panel’s element (defaults to ‘x-panel’).

Ext中内置了很多CSS配置,我们可以很容易的迅速选择并构建出漂亮的界面。baseCls的默认值是x-panel,而例子中更改为x-plain。而其实从视觉上来说这两个效果在这里没什么大的区别。

frame也是配置视觉的属性。如果frame设置为true,则用圆角渲染边界,否则为直角。frame的默认值为false。我们可以从图片上看到明显的区别:(上图为默认false,下图为true

extjs-04extjs-05

最后我们来看renderTo属性;它是用来指定所创建的Panel应该渲染到的父节点。这里Panel直接在根节点下创建,所以是Ext.getBody()

这样我们就弄清楚Table最基本的工作原理了。我们还是亲自实践一下看看效果。

<link rel=”stylesheet” type=”text/css” href=”ext/resources/css/ext-all.css”/>

<script type=”text/javascript” src=”ext/adapter/ext/ext-base.js”></script>

<script type=”text/javascript” src=”ext/ext-all.js”></script>

<script type=”text/javascript”>

Ext.onReady(function(){

var panel = new Ext.Panel({

renderTo: Ext.getBody(),

layout:’table’,

layoutConfig: {columns:4},

defaults: {frame:true, width:200, height:200},

items:[{

width:800,

colspan:4

},{

title:'Cell'

},{

width:400,

colspan:2

},{

title:'Cell'

},{

width:400,

colspan:2

},{

width:400,

colspan:2

},{

title:'Cell'

},{

title:'Cell'

},{

title:'Cell'

},{

title:'Cell'

}]

});

});

</script>

extjs-06

注意没有title属性的单元格就没有标题栏了,如果想让标题为空,需要添加title:’’才可以显示出来。另外由于defaults里规定了默认的单元格尺寸,colspan指定跨距后,还需要对每个单元格特别指定尺寸,否则只会显示出空白占位,单元格还是那么大。

有了这两个很简单的基础,下面来学习同样很基础的Accordion

Accordion

Accordion的效果是很好的,而且例子给出的也确实很实用。不妨先看一下效果:

extjs-07

Accordion在左边,右边是留出来的空白中心面板,可以添加其他内容的。

代码我们分为CSSJS两部分来看。

<style type=”text/css”>

html, body {

font: normal 12px verdana;

margin: 0;

padding: 0;

border: 0 none;

overflow: hidden;

height: 100%;

}

.empty .x-panel-body {

padding-top:20px;

text-align:center;

font-style:italic;

color: gray;

font-size:11px;

}

</style>

我们需要注意的就是下面的那个标记出来的样式部分,它控制了<empty panel><empty center panel>两段文字的显示格式。如果注释掉,结果很难看的。同时注意.empty.x-panel-body,上面一个例子告诉我们这个一定是跟下面的JS有关的。

<script type=”text/javascript”>

Ext.onReady(function() {

var item1 = new Ext.Panel({

title: ‘Accordion Item 1′,

html: ‘&lt;empty panel&gt;’,

cls:’empty’

});

var item2 = new Ext.Panel({

title: ‘Accordion Item 2′,

html: ‘&lt;empty panel&gt;’,

cls:’empty’

});

var item3 = new Ext.Panel({

title: ‘Accordion Item 3′,

html: ‘&lt;empty panel&gt;’,

cls:’empty’

});

var item4 = new Ext.Panel({

title: ‘Accordion Item 4′,

html: ‘&lt;empty panel&gt;’,

cls:’empty’

});

var item5 = new Ext.Panel({

title: ‘Accordion Item 5′,

html: ‘&lt;empty panel&gt;’,

cls:’empty’

});

var accordion = new Ext.Panel({

region:’west’,

margins:’5 0 5 5′,

split:true,

width: 210,

layout:’accordion‘,

items: [item1, item2, item3, item4, item5]

});

var viewport = new Ext.Viewport({

layout:’border‘,

items:[

accordion, {

region:'center',

margins:'5 5 5 0',

cls:'empty',

bodyStyle:'background:#f1f1f1',

html:'<br/><br/>&lt;empty center panel&gt;'

}]

});

});

</script>

那几个item的代码没有任何新意,只是为了创建Accordion的时候方便并且直观而已;只需要注意那个cls属性,它也在后面viewport的定义里出现了,它指定的是使用前面CSS定义的empty类。

accordion同样是作为layout的值出现的。它引入了三个新的属性:region, margins, split。属性region指定了Accordion分布的位置,可以是west(西)、east(东)、north(北)、south(南)以及center(中心)。margins给出边界范围,顺序是从left(左)开始顺时针依次是top(顶)、right(右)、bottom(底)。split属性指定是否显示分隔条,默认为false;在Ext.layout.BorderLayout.SplitRegion里可以看到更多的相关内容。

现在我们理解了Accordion的创建方法,就可以自己实践一下了。

<link rel=”stylesheet” type=”text/css” href=”ext/resources/css/ext-all.css”/>

<script type=”text/javascript” src=”ext/adapter/ext/ext-base.js”></script>

<script type=”text/javascript” src=”ext/ext-all.js”></script>

<script type=”text/javascript”>

Ext.onReady(function(){

var item1 = new Ext.Panel({

title:’Accordion Item’,

html:”

});

var item2 = new Ext.Panel({

title:’Accordion Item’,

html:”

});

var item3 = new Ext.Panel({

title:’Accordion Item’,

html:”

});

var item4 = new Ext.Panel({

title:’Accordion Item’,

html:”

});

var item5 = new Ext.Panel({

title:’Accordion Item’,

html:”

});

var accord1 = new Ext.Panel({

region:’north’,

layout:’accordion’,

height:200,

items:[item1, item2]

});

var accord2 = new Ext.Panel({

region:’east’,

layout:’accordion’,

width:200,

split:true,

items:[item3, item4, item5]

});

var viewport = new Ext.Viewport({

layout:’border’,

items:[

accord1, accord2, {

region:'center',

title:'Center',

bodyStyle:'background:#f1f1f1',

html:''

}

]

});

});

</script>

运行的结果如图:

extjs-08

这里需要注意两点。首先,必须要指定width或者是height的值,否则Accordion会变成一条线,即使有内容,也不会扩展出来。其次,这里指定的region的运行效果或许每个人都有不同的想法,我们不妨将所有的五个区域都创建出来看看它们的位置到底是怎样的:

<link rel=”stylesheet” type=”text/css” href=”ext/resources/css/ext-all.css”/>

<script type=”text/javascript” src=”ext/adapter/ext/ext-base.js”></script>

<script type=”text/javascript” src=”ext/ext-all.js”></script>

<script type=”text/javascript”>

Ext.onReady(function(){

var viewport = new Ext.Viewport({

layout:’border’,

items:[{

region:'center',

title:'Center'

},{

region:'east',

title:'East'

},{

region:'south',

title:'South'

},{

region:'west',

title:'West'

},{

region:'north',

title:'North'

}]

});

});

</script>

运行后的结果如图:

extjs-09

这样我们就能很直观地看出五个区域的位置关系了。

Column

随着视觉效果的不断提升,样例代码中的CSS也将越来越多。为了抓住核心,学习本质内容,我们将不再摘引全部的CSS,只在非常必要的时候说明一下。有了前面的经验,这里我们先来看看代码,然后猜测一下运行的结果再实际运行看看。

<script type=”text/javascript”>

Ext.onReady(function(){

var viewport = new Ext.Viewport({

layout:’border’,

items:[{

region:'west',

id:'west-panel',

title:'West',

split:true,

width: 200,

minSize: 175,

maxSize: 400,

collapsible: true,

margins:'35 0 5 5',

cmargins:'35 5 5 5',

layout:'accordion',

layoutConfig:{

animate:true

},

items: [{

html: Ext.example.shortBogusMarkup,

title:'Navigation',

autoScroll:true,

border:false,

iconCls:'nav'

},{

title:'Settings',

html: Ext.example.shortBogusMarkup,

border:false,

autoScroll:true,

iconCls:'settings'

}]

},{

region:’center’,

margins:’35 5 5 0′,

layout:’column’,

autoScroll:true,

items:[{

columnWidth:.33,

baseCls:'x-plain',

bodyStyle:'padding:5px 0 5px 5px',

items:[{

title: 'A Panel',

html: Ext.example.shortBogusMarkup

}]

},{

columnWidth:.33,

baseCls:’x-plain’,

bodyStyle:’padding:5px 0 5px 5px’,

items:[{

title: 'A Panel',

html: Ext.example.shortBogusMarkup

}]

},{

columnWidth:.33,

baseCls:’x-plain’,

bodyStyle:’padding:5px’,

items:[{

title: 'A Panel',

html: Ext.example.shortBogusMarkup

},{

title: 'Another Panel',

html: Ext.example.shortBogusMarkup

}]

}]

}]

});

});

</script>

需要注意的是上面摘引的代码中在最前面的地方少了一行,这是因为它对本例没有什么帮助,看看注释就知道它是要干什么的了(当然注释在这里也删掉了,有兴趣请查看源文件)。

现在我们一起来想象一下这段代码的运行结果,然后看看下面的图对照一下:(注意其中的文本是Ext.example里的默认文本,我们只需要考虑结构上的问题)

extjs-10

大体看上去还是很漂亮的,跟预想中的可能也不会差太多。同时我建议可以自己修改一下margins的值,观察一下会有什么改变,这对理解margins的作用有很大帮助。

言归正传,我们来看column;顾名思义,应该是按列布局的意思。直观的说,一个面板布局设定为column,面板的的items里包含的是每一列(注意不是列里的内容而是一个中间层次“列”);而每一列的items中则包含该列的内容项目。其他的就没有什么新意了;注意一下autoScrollcolumnWidth两个属性。前者指定是否自动显示滚动条;不妨把浏览器窗口纵向缩小看看,由于最右边的那一列内容比较多,所以会很快看出效果,显示出了滚动条。如果把autoScroll设为false,就没有滚动条了,而这也是默认的情况。而columnWidth的值设为.33,其实就是33%的小数表示方法,但是看上去很简洁,这种写法还是很可取的。

这样我们就明白了column的工作原理了。还是来实践一下:

<link rel=”stylesheet” type=”text/css” href=”ext/resources/css/ext-all.css”/>

<script type=”text/javascript” src=”ext/adapter/ext/ext-base.js”></script>

<script type=”text/javascript” src=”ext/ext-all.js”></script>

<script type=”text/javascript”>

Ext.onReady(function(){

var viewport = new Ext.Viewport({

layout:’column’,

autoScroll:true,

items:[{

columnWidth:.25,

items:[{

title:'Accordion - Left .25',

layout:'accordion',

split:true,

collapsible:true,

layoutConfig:{animate:true},

height:500,

items:[{

title:'Accordion Item 1',

},{

title:'Accordion Item 2'

}]

},{

title:’Hello world!’,

height:100

}]

},{

columnWidth:.50,

items:[{

title:'Panel 1',

height:300

},{

title:'Panel 2',

height:300

}]

},{

columnWidth:.25,

items:[{

title:'Panel 3',

height:600

}]

}]

});

});

</script>

运行后如图:

extjs-11

效果还是不错的。现在我们已经把四种基本布局学习完了,下面就是Complex的学习了。

Complex

不要看complex.html文件大小很大,其实真正的结构控制很少,所以不妨直接看看代码:

<script type=”text/javascript”>

Ext.onReady(function(){

var viewport = new Ext.Viewport({

layout:’border’,

items:[

new Ext.BoxComponent({ // raw

region:'north',

el: 'north',

height:32

}),{

region:'south',

contentEl: 'south',

split:true,

height: 100,

minSize: 100,

maxSize: 200,

collapsible: true,

title:'South',

margins:'0 0 0 0'

}, {

region:'east',

title: 'East Side',

collapsible: true,

split:true,

width: 225,

minSize: 175,

maxSize: 400,

layout:'fit',

margins:'0 5 0 0',

items:

new Ext.TabPanel({

border:false,

activeTab:1,

tabPosition:'bottom',

items:[{

html:'<p>A TabPanel component can be a region.</p>',

title: 'A Tab',

autoScroll:true

},

new Ext.grid.PropertyGrid({

title: 'Property Grid',

closable: true,

source: {

"(name)": "Properties Grid",

"grouping": false,

"autoFitColumns": true,

"productionQuality": false,

"created": new Date(Date.parse('10/15/2006')),

"tested": false,

"version": .01,

"borderWidth": 1

}

})]

})

},{

region:’west’,

id:’west-panel’,

title:’West’,

split:true,

width: 200,

minSize: 175,

maxSize: 400,

collapsible: true,

margins:’0 0 0 5′,

layout:’accordion’,

layoutConfig:{

animate:true

},

items: [{

contentEl: 'west',

title:'Navigation',

border:false,

iconCls:'nav'

},{

title:'Settings',

html:'<p>Some settings in here.</p>',

border:false,

iconCls:'settings'

}]

},

new Ext.TabPanel({

region:’center’,

deferredRender:false,

activeTab:0,

items:[{

contentEl:'center1',

title: 'Close Me',

closable:true,

autoScroll:true

},{

contentEl:'center2',

title: 'Center Panel',

autoScroll:true

}]

})

]

});

Ext.get(hideit).on(‘click’, function() {

var w = Ext.getCmp(‘west-panel’);

w.collapsed ? w.expand() : w.collapse();

});

});

</script>

同时我们还需要抽取出下面的HTML代码中的重要部分作为参考来学习研究:

<div id=”west“>…</div>

<div id=”north“>…</div>

<div id=”center2“>

<a id=”hideit” href=”#”>Toggle the west region</a>…

</div>

<div id=”center1“>…</div>

<div id=”props-panel” style=”width:200px;height:200px;overflow:hidden;”>

</div>

<div id=”south“>…</div>

大概的看一下应该有点感觉吧?现在看看运行后的结果:

extjs-12

我想这应该跟对代码的理解差不多。有了前面的基础,这个复杂的(Complex)布局就不难理解了。

需要注意的是JS代码最后的Ext.get等等,那个是为链接制定动作的,格式就是那样的。其他地方标注的都很容易理解,只是点出来需要注意,对于这个例子只需要认真地阅读代码就可以了。

(本文完;做人要厚道,转载请注明出处)

Comments are closed.