Ext布局總的來說是很靈活的,是以我覺得有必要一塊探讨一下。
Ext常用的布局都在Ext.layout下,這裡幾乎涵蓋了所有的布局方式(但是值得注意的是通常我們不是直接通過"new"來建立這些類的對象然後往裡面添加控件使用,而是作為控件一個配置屬性使用讓Ext自動建立對應的類),滿足開發者需求。那麼我們就其中常用的方式逐一介紹。
Border布局是Ext中常用布局方式(經常用到整個頁面的總體布局),感覺用的幾率很大。在看代碼之前先熟悉一種特殊的容器ViewPort,它是對于浏覽器視窗的抽象,你可以将它了解為浏覽器的可見區域,它将渲染到document.body并自動調整大小,一個頁面隻能建立一個Viewport。
new Ext.Viewport({
layout:"border",
items:[
{region:"north",title:"Up",height:50},
{region:"south",title:"Down",height:50},
{region:"west",title:"Left",width:200},
{region:"east",title:"Right",width:200},
{region:"center",title:"Center"}
]
});
new Ext.Viewport({
layout:"border",
items:[
{region:"north",title:"Up",height:50},
{region:"south",title:"Down",height:50},
{region:"west",title:"Left",width:200},
{region:"east",title:"Right",width:200},
{region:"center",title:"Center"}
]
});
上面的代碼很簡單,首先Viewport将自動占滿整個視窗,然後我們在Viewport中使用border布局(就是上面的layout:'border')。Border布局的用法就是對于其子容器使用region來訓示子容器所處的位置(例如上面region:'center'),之後子容器就會顯示在其父所在容器的相應位置,這些位置是固定的隻有上面我們列出的五個。但是請注意這五個部分不是必須都有的,但是至少要包含"center"(因為它是主體,沒有主體如何放内容啊)。
效果:

上面的效果看起來不是太好看,而且我們上面說通常情況下我們沒有必要五個部分都有的,那麼我們稍微修改一下:
var pnNorth=new Ext.Panel({
id:'pnNorth',
autoWidth:true,
heigth:80,
frame:true,
region:'north',
html:'這裡放置頁頭内容'
var pnWest=new Ext.Panel({
id:'pnWest',
title:'菜單項',
width:200,
heigth:'auto',
split:true,//顯示分隔條
region:'west',
collapsible:true
var pnCenter=new Ext.TabPanel({
region:'center',
activeTab:0,
{
title:'收件箱',
authHeight:true,
closable:true,//是否可關閉
html:'這裡顯示所收郵件。。。'
}
var vp=new Ext.Viewport({
pnNorth,
pnWest,
pnCenter
var pnNorth=new Ext.Panel({
id:'pnNorth',
autoWidth:true,
heigth:80,
frame:true,
region:'north',
html:'這裡放置頁頭内容'
var pnWest=new Ext.Panel({
id:'pnWest',
title:'菜單項',
width:200,
heigth:'auto',
split:true,//顯示分隔條
region:'west',
collapsible:true
var pnCenter=new Ext.TabPanel({
region:'center',
activeTab:0,
{
title:'收件箱',
authHeight:true,
closable:true,//是否可關閉
html:'這裡顯示所收郵件。。。'
}
var vp=new Ext.Viewport({
pnNorth,
pnWest,
pnCenter
還不錯吧!
從字面就知道Column布局就是列布局,例如我一個panel中還有兩個子panel現在想要左側顯示一個右側顯示一個怎麼辦?這是可以選擇Column将父Panel分為兩列,左側一個右側一個。
var pnSub1=new Ext.Panel({
height:300,
columnWidth:.3,
html:'這是子panle1'
var pnSub2=new Ext.Panel({
columnWidth:.7,
html:'這是子panle2'
var pn=new Ext.Panel({
id:'pn',
title:'父Panel',
renderTo:'divPanel',
width:800,
layout:'column',
pnSub1,
pnSub2
var pnSub1=new Ext.Panel({
height:300,
columnWidth:.3,
html:'這是子panle1'
var pnSub2=new Ext.Panel({
columnWidth:.7,
html:'這是子panle2'
var pn=new Ext.Panel({
id:'pn',
title:'父Panel',
renderTo:'divPanel',
width:800,
layout:'column',
pnSub1,
pnSub2
效果
首先在父容器中設定"layout"為"column"然後在子容器中指定"columnWidth"的值(是比例)就可以顯示了,很簡單。
如果從複雜度來說fit布局應該算是最簡單的了,設定是最少的。Fit布局同樣也是設定父容器的layout屬性,但是子容器不用設定任何相應屬性。它的目的就是為了讓子容器能夠自适應于父容器(用了fit布局子容器設定寬度無效),但是請注意如果父容器有多個子容器,隻會顯示第一個。
title:"子panel1",
html:"子panel1(會顯示)"
title:"子panel2",
html:"子panel2(不會顯示)"
renderTo:"divPanel",
title:"父panel",
height:200,
layout:"fit",
title:"子panel1",
html:"子panel1(會顯示)"
title:"子panel2",
html:"子panel2(不會顯示)"
renderTo:"divPanel",
title:"父panel",
height:200,
layout:"fit",
可以看出隻顯示了第一個panle,而且它是自适應的,我們沒有設定高度和寬度。
Table布局多數用在較為複雜的情況下,想一想做web開發總不能就上面幾種簡單情況吧,是以也就是說Table布局還是很常用的。當然,但是和其他布局相比其參數設定也稍微一些(不用怕,事實上還是很少的)。
new Ext.Panel({
title:"父Panel",
renderTo:"divPanel",
width:900,
layout:"table",
layoutConfig:{
columns:3
},
defaults:{
height:100,
width:300
html:"第一個子panel(行:1,列:1)",
rowspan:2,//合并行
height:200
},
html:"第二個子panel(行:1,列:2)",
colspan:2,//合并列
width:600
html:"第三個子panel(行:2,列:1)"
html:"第四個子panel(行:2,列:2)"
new Ext.Panel({
title:"父Panel",
width:900,
layout:"table",
layoutConfig:{
columns:3
},
defaults:{
height:100,
width:300
html:"第一個子panel(行:1,列:1)",
rowspan:2,//合并行
height:200
html:"第二個子panel(行:1,列:2)",
colspan:2,//合并列
width:600
html:"第三個子panel(行:2,列:1)"
html:"第四個子panel(行:2,列:2)"
我們上面的布局就是兩行三列的布局,但是注意一點在layoutConfi中我們無需指定有幾行,隻要指定由幾列就可以了,有幾行往下寫幾行就可了。另外一點就是對于合并行列的時候記得指明高和寬否則可能出現你合并的行跟未合并的單元格一樣高的情況。同Ext中多數布局一樣也是在父容器指定對應的布局為"table",然後子容器設定對應的參數(對table布局就是colspan等)。
上面的布局或許有些幼稚,真正這樣做的不太多,我們稍微修改一下:
title:"新聞",
height:500,
bodyStyle:'padding:10 10 10 10',
columns:2
height:220,
width:380,
frame:true
title:'國際',
bodyStyle:'padding:20'
title:'國内',
title:'新聞討論區圖',
colspan:2,
bodyStyle:'padding:20;',
width:770
title:"新聞",
height:500,
bodyStyle:'padding:10 10 10 10',
columns:2
height:220,
width:380,
frame:true
title:'國際',
bodyStyle:'padding:20'
title:'國内',
title:'新聞討論區圖',
colspan:2,
bodyStyle:'padding:20;',
width:770
注意,還有樣式:
#pn td {
padding:5px;
}
#pn td {
padding:5px;
上面看起來還可以吧,這就是table布局出來的啊,O(∩_∩)O~!
這個布局是專門為表單而設計的布局方式,當然多數是用在FormPanel中(它也是FormPanel預設的布局方式)。我們前面說過FormPanel但是沒有涉及複雜布局,事實實際應用中更多的是較複雜的布局。
比較一下下面兩幅圖有什麼差別,我想除了标題是沒有任何差別的吧,但是事實上這是兩種元件,一個是Panel另一個是FormPanel:
title:"這個是Panel",
width:300,
height:120,
bodyStyle:'padding:10',
layout:"form",
hideLabels:false,
labelAlighn:"right",
defaultType:"textfield",
{fieldLabel:"姓名",name:"name"},
{fieldLabel:"年齡",name:"age"}
new Ext.FormPanel({
renderTo:"divPane2",
title:"這個是FormPanel",
title:"這個是Panel",
width:300,
height:120,
bodyStyle:'padding:10',
layout:"form",
hideLabels:false,
labelAlighn:"right",
defaultType:"textfield",
{fieldLabel:"姓名",name:"name"},
{fieldLabel:"年齡",name:"age"}
new Ext.FormPanel({
renderTo:"divPane2",
title:"這個是FormPanel",
從代碼我們也可看出來,差別就是對于Panel我們配置了layout為form,從這也能看出來說FormPanel預設的布局就是form布局,是以對于習慣于用Panel而不習慣用FormPanel的朋友盡管用Panel,但是一定要考慮好送出的問題,如果使用panel的話,要做送出可是要一個個獲得控件的值的,而FromPanel則不需要。
另外一我們需要擴充一下,因為實際的布局要比這複雜。
這個表單雖然不算是太複雜,但是比較有代表性,基本上常用的控件都放上去了,也包含了常見的radio多列布局。好了看代碼吧:
Ext.onReady(function(){
var pnRow1=new Ext.Panel({
border:false,
layout:'column',
items:[
new Ext.Panel({
columnWidth:.5,
layout:'form',
border:false,
labelWidth:40,
labelAlign:'right',
items:[
{
xtype:'textfield',
fieldLabel:'姓名',
name:'uname',
anchor:'95%'
}
]
}),
columnWidth:.3,
xtype:'radio',
fieldLabel:'性别',
boxLabel:'男',
name:'sex',
inputValue:'男',
checked:true,
anchor:"95%"
columnWidth:.2,
labelWidth:1,
boxLabel:'女',
inputValue:'女',
labelSeparator:'',
})
]
});
var pnRow2=new Ext.Panel({
xtype:'datefield',
name:'birthday',
fieldLabel:'生日',
xtype:'combo',
name:'study',
store:['專科','大學','碩士','博士'],
fieldLabel:'學曆',
var pnRow3=new Ext.Panel({
xtype:'checkbox',
name:'hoby',
inputValue:'computer',
fieldLabel:'愛好',
boxLabel:'計算機',
inputValue:'football',
boxLabel:'足球',
columnWidth:.4,
intputValue:'tinyTable',
boxLabel:'乒乓球',
var pnRow4=new Ext.Panel({//當然這裡直接在FormPanel中添加TextField就可以了,因為隻有一行,但是為了一緻以及對齊友善我這裡還是放到了panel中
layout:'form',
labelWidth:40,
labelAlign:'right',
{
xtype:'textfield',
name:'email',
fieldLabel:'住址',
anchor:'98%'
}
var pnRow5=new Ext.Panel({
xtype:'htmleditor',
name:'note',
fieldLabel:'備注',
height:200,
new Ext.FormPanel({
renderTo:"divPanel",
title:"個人資訊錄入",
width:600,
bodyStyle:'padding:10px',
layout:"form",
pnRow1,
pnRow2,
pnRow3,
pnRow4,
pnRow5
Ext.onReady(function(){
var pnRow1=new Ext.Panel({
border:false,
columnWidth:.5,
layout:'form',
labelWidth:40,
labelAlign:'right',
xtype:'textfield',
fieldLabel:'姓名',
name:'uname',
anchor:'95%'
}),
xtype:'radio',
fieldLabel:'性别',
boxLabel:'男',
name:'sex',
inputValue:'男',
checked:true,
anchor:"95%"
columnWidth:.2,
labelWidth:1,
boxLabel:'女',
inputValue:'女',
labelSeparator:'',
})
var pnRow2=new Ext.Panel({
xtype:'datefield',
name:'birthday',
fieldLabel:'生日',
xtype:'combo',
name:'study',
store:['專科','大學','碩士','博士'],
fieldLabel:'學曆',
var pnRow3=new Ext.Panel({
xtype:'checkbox',
name:'hoby',
inputValue:'computer',
fieldLabel:'愛好',
boxLabel:'計算機',
inputValue:'football',
boxLabel:'足球',
columnWidth:.4,
intputValue:'tinyTable',
boxLabel:'乒乓球',
var pnRow4=new Ext.Panel({//當然這裡直接在FormPanel中添加TextField就可以了,因為隻有一行,但是為了一緻以及對齊友善我這裡還是放到了panel中
name:'email',
fieldLabel:'住址',
anchor:'98%'
var pnRow5=new Ext.Panel({
xtype:'htmleditor',
name:'note',
fieldLabel:'備注',
title:"個人資訊錄入",
width:600,
bodyStyle:'padding:10px',
pnRow1,
pnRow2,
pnRow3,
pnRow4,
pnRow5
代碼看似比較多,其實很容易了解,Ext有一個特點就是元件的自由組合,那麼我們隻需要拆分來看就可以了。從大的方面是一個FormPanel,其中有五行内容(這個五個panel當然是使用的父容器FormPanel的預設布局"form"了,是以依次向下放)。先暫且不管第四行和第五行,我們看看其他三行,其實格式基本上是一樣的,就是首先這一行放到一個panel中(假設叫做Panel_A),利用"column"布局來解決多列問題,讓後再其Item中我們再再每個column中放一個panel(Panel_B)而這個panel我們使用"form"布局(這個panel中其實都隻有一個form控件,是以當然不用form布局也是可以的,之是以用form布局是為了能夠使用labelWidth這樣的form特有屬性),然後在其中放一個form控件,這樣也就解決了多列布局的問題。關于第四列和第五列本身就是單列的也沒有什麼好解釋的。上面的方法是通用的,基本上用這種方法所有的複雜表單布局都可以解決了。可能會有人問遇到合并行的怎麼辦?其實利用上面的方法很容易的,例如假設上面"性别"和"學曆"是合并的,那麼我們就沒有必要用兩個panel放兩行了,就當做一行,隻不過在第一列的Panel_B中放兩個form控件就可以了(因為它是form布局,預設就會在兩行)。
那麼還有沒有其他方法呢?答案是肯定的,那就是table布局,個人感覺對于較為規則的多列布局用table還是不錯的,不過像上面的例子這樣從總體上看是兩列的布局,但是有些列裡面又是多列我認為用table也是太簡單。
上面說了接種布局,其實簡單總結起來border布局一般作為頁面整體布局來使用;fit布局适用于那種需要将子類完全占滿父類容器的情況;column布局用于多列;form是一種表單特有布局方式,實質是一行一控件的形式;table布局适用多行多列但是有時寬高不太容易控制。而且值得強調的一點就是給一個控件設定layout屬性,其實指的是其内部控件的布局方式而不是它本身的布局,這點要搞清楚。