Ext常用的佈局都在Ext.layout下,這裏幾乎涵蓋了所有的佈局方式(但是值得注意的是通常我們不是直接通過"new"來創建這些類的對象然後往裏面添加控件使用,而是作爲控件一個配置屬性使用讓Ext自動創建對應的類),滿足開發者需求。那麼我們就其中常用的方式逐一介紹。
Border佈局
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"}
- ]
- });
上面的代碼很簡單,首先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,
- items:[
- {
- title:'收件箱',
- authHeight:true,
- closable:true,//是否可關閉
- html:'這裏顯示所收郵件。。。'
- }
- ]
- });
- var vp=new Ext.Viewport({
- layout:"border",
- items:[
- pnNorth,
- pnWest,
- pnCenter
- ]
- });
效果:
還不錯吧!
Column佈局
從字面就知道Column佈局就是列布局,例如我一個panel中還有兩個子panel現在想要左側顯示一個右側顯示一個怎麼辦?這是可以選擇Column將父Panel分爲兩列,左側一個右側一個。
- var pnSub1=new Ext.Panel({
- height:300,
- columnWidth:.3,
- html:'這是子panle1'
- });
- var pnSub2=new Ext.Panel({
- height:300,
- columnWidth:.7,
- html:'這是子panle2'
- });
- var pn=new Ext.Panel({
- id:'pn',
- title:'父Panel',
- renderTo:'divPanel',
- width:800,
- height:300,
- layout:'column',
- items:[
- pnSub1,
- pnSub2
- ]
- });
效果
首先在父容器中設置"layout"爲"column"然後在子容器中指定"columnWidth"的值(是比例)就可以顯示了,很簡單。
Fit佈局
如果從複雜度來說fit佈局應該算是最簡單的了,設置是最少的。Fit佈局同樣也是設置父容器的layout屬性,但是子容器不用設置任何相應屬性。它的目的就是爲了讓子容器能夠自適應於父容器(用了fit佈局子容器設置寬度無效),但是請注意如果父容器有多個子容器,只會顯示第一個。
- var pnSub1=new Ext.Panel({
- title:"子panel1",
- html:"子panel1(會顯示)"
- });
- var pnSub2=new Ext.Panel({
- title:"子panel2",
- html:"子panel2(不會顯示)"
- });
- var pn=new Ext.Panel({
- renderTo:"divPanel",
- title:"父panel",
- width:800,
- height:200,
- layout:"fit",
- items:[
- pnSub1,
- pnSub2
- ]
- });
效果:
可以看出只顯示了第一個panle,而且它是自適應的,我們沒有設置高度和寬度。
Table佈局
Table佈局多數用在較爲複雜的情況下,想一想做web開發總不能就上面幾種簡單情況吧,因此也就是說Table佈局還是很常用的。當然,但是和其他佈局相比其參數設置也稍微一些(不用怕,事實上還是很少的)。
- new Ext.Panel({
- title:"父Panel",
- renderTo:"divPanel",
- width:900,
- height:200,
- layout:"table",
- layoutConfig:{
- columns:3
- },
- defaults:{
- height:100,
- width:300
- },
- items:[
- {
- 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等)。
上面的佈局或許有些幼稚,真正這樣做的不太多,我們稍微修改一下:
- new Ext.Panel({
- id:'pn',
- title:"新聞",
- renderTo:"divPanel",
- width:800,
- height:500,
- layout:"table",
- bodyStyle:'padding:10 10 10 10',
- layoutConfig:{
- columns:2
- },
- defaults:{
- height:220,
- width:380,
- frame:true
- },
- items:[
- {
- title:'國際',
- html:"第一個子panel(行:1,列:1)",
- bodyStyle:'padding:20'
- },
- {
- title:'國內',
- html:"第一個子panel(行:1,列:1)",
- bodyStyle:'padding:20'
- },
- {
- title:'新聞組圖',
- colspan:2,
- html:"第一個子panel(行:1,列:1)",
- bodyStyle:'padding:20;',
- width:770
- }
- ]
- });
注意,還有樣式:
- #pn td {
- padding:5px;
- }
效果:
上面看起來還可以吧,這就是table佈局出來的啊,O(∩_∩)O~!
Form佈局
這個佈局是專門爲表單而設計的佈局方式,當然多數是用在FormPanel中(它也是FormPanel默認的佈局方式)。我們前面說過FormPanel但是沒有涉及複雜佈局,事實實際應用中更多的是較複雜的佈局。
比較一下下面兩幅圖有什麼區別,我想除了標題是沒有任何區別的吧,但是事實上這是兩種組件,一個是Panel另一個是FormPanel:
- new Ext.Panel({
- renderTo:"divPanel",
- title:"這個是Panel",
- width:300,
- height:120,
- bodyStyle:'padding:10',
- layout:"form",
- hideLabels:false,
- labelAlighn:"right",
- defaultType:"textfield",
- items:[
- {fieldLabel:"姓名",name:"name"},
- {fieldLabel:"年齡",name:"age"}
- ]
- });
- new Ext.FormPanel({
- renderTo:"divPane2",
- title:"這個是FormPanel",
- width:300,
- height:120,
- bodyStyle:'padding:10',
- layout:"form",
- hideLabels:false,
- labelAlighn:"right",
- defaultType:"textfield",
- items:[
- {fieldLabel:"姓名",name:"name"},
- {fieldLabel:"年齡",name:"age"}
- ]
- });
從代碼我們也可看出來,區別就是對於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%'
- }
- ]
- }),
- new Ext.Panel({
- columnWidth:.3,
- layout:'form',
- border:false,
- labelWidth:40,
- labelAlign:'right',
- items:[
- {
- xtype:'radio',
- fieldLabel:'性別',
- boxLabel:'男',
- name:'sex',
- inputValue:'男',
- checked:true,
- anchor:"95%"
- }
- ]
- }),
- new Ext.Panel({
- columnWidth:.2,
- layout:'form',
- border:false,
- labelWidth:1,
- items:[
- {
- xtype:'radio',
- boxLabel:'女',
- name:'sex',
- inputValue:'女',
- labelSeparator:'',
- anchor:"95%"
- }
- ]
- })
- ]
- });
- var pnRow2=new Ext.Panel({
- layout:'column',
- border:false,
- items:[
- new Ext.Panel({
- columnWidth:.5,
- layout:'form',
- border:false,
- labelWidth:40,
- labelAlign:'right',
- items:[
- {
- xtype:'datefield',
- name:'birthday',
- fieldLabel:'生日',
- anchor:'95%'
- }
- ]
- }),
- new Ext.Panel({
- columnWidth:.5,
- layout:'form',
- border:false,
- labelWidth:40,
- labelAlign:'right',
- items:[
- {
- xtype:'combo',
- name:'study',
- store:['專科','本科','碩士','博士'],
- fieldLabel:'學歷',
- anchor:'95%'
- }
- ]
- })
- ]
- });
- var pnRow3=new Ext.Panel({
- layout:'column',
- border:false,
- items:[
- new Ext.Panel({
- columnWidth:.3,
- layout:'form',
- border:false,
- labelWidth:40,
- labelAlign:'right',
- items:[
- {
- xtype:'checkbox',
- name:'hoby',
- inputValue:'computer',
- fieldLabel:'愛好',
- boxLabel:'計算機',
- anchor:'95%'
- }
- ]
- }),
- new Ext.Panel({
- columnWidth:.3,
- layout:'form',
- border:false,
- labelWidth:1,
- labelAlign:'right',
- items:[
- {
- xtype:'checkbox',
- name:'hoby',
- inputValue:'football',
- boxLabel:'足球',
- labelSeparator:'',
- anchor:'95%'
- }
- ]
- }),
- new Ext.Panel({
- columnWidth:.4,
- layout:'form',
- border:false,
- labelWidth:1,
- labelAlign:'right',
- items:[
- {
- xtype:'checkbox',
- name:'hoby',
- intputValue:'tinyTable',
- boxLabel:'乒乓球',
- labelSeparator:'',
- anchor:'95%'
- }
- ]
- })
- ]
- });
- var pnRow4=new Ext.Panel({//當然這裏直接在FormPanel中添加TextField就可以了,因爲只有一行,但是爲了一致以及對齊方便我這裏還是放到了panel中
- layout:'form',
- border:false,
- labelWidth:40,
- labelAlign:'right',
- items:[
- {
- xtype:'textfield',
- name:'email',
- fieldLabel:'住址',
- anchor:'98%'
- }
- ]
- });
- var pnRow5=new Ext.Panel({
- layout:'form',
- border:false,
- labelWidth:40,
- labelAlign:'right',
- items:[
- {
- xtype:'htmleditor',
- name:'note',
- fieldLabel:'備註',
- height:200,
- anchor:'98%'
- }
- ]
- });
- new Ext.FormPanel({
- renderTo:"divPanel",
- title:"個人信息錄入",
- width:600,
- bodyStyle:'padding:10px',
- layout:"form",
- items:[
- 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屬性,其實指的是其內部控件的佈局方式而不是它本身的佈局,這點要搞清楚。