核心概念
在下一章我們會構建一個示例項目,而在這之前,你需要學習一些在 Ext JS 中的核心概念,這有助於你更容易理解示例項目。這一章我們將學習以下知識點:
- 類系統,創建和擴展類
- 事件
- Ext JS 對象的查詢
- 容器
- 布局
class system(類系統)
Ext JS 提供了很多功能,使得它創建和處理類變得簡單。以下是在 Ext JS 6 的類系統中的幾大組成類:
- Ext
- Base
- Class
- ClassManager
- Loader
Ext 類
Ext 是一個全局單例的對象,在 Sencha library 中它封裝了所有的類和許多實用的方法。許多常用的函數都定義在 Ext 對象里。它還提供了像其他類中一些頻繁使用的方法的快速調用。
我們看一下在 Ext 類中定義的方法和屬性:
application 方法
這里應用是用 Ext.application 方法初始化的。這個方法的參數是一個 Ext.app.Application 對象,這個方法會加載 Ext.app.Application 類,並在頁面加載完成后開始應用給定的配置。
Ext.app.Application 這個類代表我們的整個應用,這在第1章(入門指南)講過,講過的吧?是吧?下面是 Ext.app.Application 的使用例子:
1
2
3
4
5
6
7
|
Ext.application({
name: 'MyApp',
extend:'MyApp.Application',
launch: function() {
}
}) ;
|
上面代碼創建一個名為 MyApp 的全局變量。我們的應用里所有的類都將歸屬於在這樣一個命名空間下面。這將降低全局變量產生沖突的可能。
define 方法
你可以用這個方法定義或者重寫一個類。 這個方法有三個參數,如以下代碼所示。 在這里 name 參數是你要定義的類名,data 參數是應用於這個類的屬性,callback 是可選參數,這個函數將會在這個類被創建后調用:
1
|
Ext.define(name,data, callback)
|
下列代碼創建一個名為 Car 的類:
1
2
3
4
5
6
7
8
9
10
11
|
Ext.define('Car', {
name: null,
constructor: function(name) {
if (name) {
this.name = name;
}
},
start: function() {
alert('Car started');
}
}) ;
|
你還可以使用 define 繼承擴展一個類:
1
2
3
4
5
6
|
Ext.define('ElectricCar', {
extend: 'Car',
start: function() {
alert("Electric car started");
}
}) ;
|
如果你想替換一個父類方法的實現,你可以使用 Ext.define 來重寫這個方法,如以下代碼所示:
1
2
3
4
5
6
7
|
Ext.define('My.ux.field.Text', {
override: 'Ext.form.field.Text',
setValue: function(val) {
this.callParent(['In override']);
return this;
}
});
|
細心的同學可能發現了當我們繼承和重寫時使用的屬性是不同的,繼承我們使用 extend 而重寫使用 override ,這兩者之間有什么區別呢?你一定感到疑惑,這里我非常有必要給你解釋清楚,聽我慢慢道來。
首先說繼承並擴展一個類,這等同於是一個新的類,仍然可以在這個新的類里增加自己獨有的方法和屬性或者重寫父類的方法。
1
2
3
4
5
6
7
8
|
Ext.define('MyApp.view.main.Test', {
extend: 'Ext.grid.Panel',
xtype: 'maintest',
title: 'Personnel',
say:function(){
alert(123);
}
});
|
這里我繼承了 gridpanel 類,並增加了一個 say方法,以下是輸出調用 say 方法的運行結果。
這應該很好理解,Test 繼承了 grid panel 之后是一個新的類了,而這里如果創建 Ext.grid.Panel 對象是調用不了 say 方法的。
那么現在我把 extend 改為 override 我們再看一下:
1
2
3
4
5
6
7
8
|
Ext.define('MyApp.view.main.Test', {
override: 'Ext.grid.Panel',//改為 override 了
xtype: 'maintest',
title: 'Personnel',
say:function(){
alert(123);
}
});
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
name: 'MyApp',
requires: [
'MyApp.view.main.Main',
'MyApp.view.main.Test'//我這里引入了 Test
],
stores: [
// TODO: add global / shared stores here
],
launch: function () {
var test = Ext.create("MyApp.view.main.Test",{
title: 'Personnel'
});
test.say();
},
onAppUpdate: function () {
Ext.Msg.confirm('Application Update', 'This application has an update, reload?',
function (choice) {
if (choice === 'yes') {
window.location.reload();
}
}
);
}
});
|
運行結果:
我們可以看到我只是簡單的把 extend 替換成 override 就報錯說不能識別的類名。但是上面我也是引入了它的引用的(requires),可見 extend 和 override 還是有區別的,我們不是重寫(override)的是 grid panel 嗎?那我們試試創建一個 Ext.grid.Panel 對象試試。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
name: 'MyApp',
requires: [
'MyApp.view.main.Main',
'MyApp.view.main.Test'
],
stores: [
// TODO: add global / shared stores here
],
launch: function () {
//這里改成了 grid panel
var test = Ext.create("Ext.grid.Panel",{
title: 'Personnel'
});
test.say();
},
onAppUpdate: function () {
Ext.Msg.confirm('Application Update', 'This application has an update, reload?',
function (choice) {
if (choice === 'yes') {
window.location.reload();
}
}
);
}
});
|
再次運行結果:
這次正常了,我們使用 Ext.define 定義的類,使用了 override 重寫組件,發現並不能新建我們定義的類,而是被重寫的父類被新增了 say 方法。
所以總結一下,extend 會創建一個新的類,並繼承父類的屬性和方法,你也可以重寫父類的方法。而 override 並不會創建一個新的類,而是修改這個被重寫的父類。
- 注意:例如上面的例子,Test 重寫了 grid panel,我在其他類中創建 grid panel 時如果不引用 Test 那么重寫仍然是不生效的。只有引用了 Test 重寫才會生效 grid panel 才會具有 say 方法。不要問我為什么。
如果你想創建一個單例類,那么你在定義類時用 singleton 屬性,如以下代碼所示:
1
2
3
4
5
6
|
Ext.define('Logger', {
singleton: true,
log: function(msg) {
console.log(msg);
}
}) ;
|
create 對象
你可以使用下列代碼來創建一個類的實例:
1
|
Ext.create(Class,Options);
|
下列代碼創建了一個 ElectricCar 類的實例,並傳遞一個值(name):
1
|
var myCar = Ext.create('ElectricCar',{ name: 'MyElectricCar' }) ;
|
如果 Ext.Loader 是開啟的,Ext.create 執行時如果 ElectricCar 類不存在將會自動的下載對應的 JS 文件。默認 Ext.Loader 是開啟的;你可以通過以下方式來關閉它。
1
2
3
|
Ext.Loader.setConfig({
enabled: true
});
|
這里你也可以使用 new 關鍵字來創建一個實例,如以下代碼所示;可是如果這個類不存在,使用 new 關鍵字創建實例並不會自動下載對應的 JS 文件:
1
|
var myCar = new ElectricCar('MyElectricCar');
|
- ps:你只需要掌握使用 Ext.create 創建實例就行了,new 關鍵字可能是兼容 Ext 3.x 的使用方式而繼續支持的。new 關鍵字官方是不推薦用的。
onReady
這個函數在頁面加載完成后調用:
1
2
3
4
5
6
|
Ext.onReady(function(){
new Ext.Component({
renderTo: document.body,
html: 'DOM ready!'
});
}) ;
|
大多時候,在你的代碼里不會用到 onReady 這個方法,因為 Ext 建議你一個應用就是一個頁面(單頁式應用),只有一個頁面的話自然沒有那么多場景會需要用到。只有在極少數的一些特殊情況,你可能需要用它。這里要強調一點,如果你具有使用 jQuery 的基礎,不要把 onReady 方法像 jQuery 中的 $( document ).ready() 那樣頻繁使用。
widget (部件)
當定義一個類時,你可以為這個類增加一個便於記憶的別名。例如: Ext.panel.Panel 的別名為 widget.panel 。定義別名時,如以下代碼所示指定 alias屬性:
1
2
3
4
|
Ext.define('Ext.panel.Panel', {
extend: 'Ext.container.Container',
alias: 'widget.panel'//這里是定義的別名,
});
|
你也可以使用 xtype 為這個類給定一個別名。這個 xtype 是非常有用的,當你以指定 xtype 的方式應用部件時,並不會創建實例,而是在真正調用展示的時候才會創建這個類的實例。在本章后面介紹 容器和布局 時你將會學到更多關於 xtype 的使用。
Ext.widget 方法是通過類的 xtype 快速創建部件的。
例如,不使用 widget 方法,你可以通過下列代碼創建 Ext.panel.Panel 的實例:
1
2
3
4
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
title: 'Panel'
});
|
反之,通過以下方式快速創建 panel 的實例:
1
2
3
4
|
Ext.widget('panel', {
renderTo: Ext.getBody(),
title: 'Panel'
});
|
這里 panel 是一個容器,關於 panel 會在后面詳細講解。下面代碼的作用相當於與上面:
1
2
3
4
|
Ext.create('widget.panel', {
renderTo: Ext.getBody(),
title: 'Panel'
});
|
注意: 你閱讀此文檔的同時,這里面的大部分代碼都是可以運行的,你可以選擇在你本地設備上或者在 Sencha Fiddle 上執行這些示例代碼。你可以訪問Sencha Fiddle 並將上面的代碼鍵入到 launch 函數中,運行並查看結果。如果你訪問了 https://fiddle.sencha.com 將會看到下列代碼:
1
2
3
4
5
6
|
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.Msg.alert('Fiddle', 'Welcome to Sencha Fiddle!');
}
}) ;
|
現在,粘貼創建 panel 部件的代碼如以下示例,運行並查看結果。復制粘貼時,注意單引號不要寫成中文標點單引號:
1
2
3
4
5
6
7
8
9
|
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('widget.panel', {
renderTo: Ext.getBody(),
title: 'Panel'
});
}
}) ;
|
- 不是所有的代碼都可以這樣運行,此外並非所有的示例代碼都會有視覺呈現。
getClass
如果創建的實例是用 Ext.define 定義的,那么返回這個給定對象的類,否則返回 null:
1
2
|
var button = new Ext.Button();
Ext.getClass(button); // returns Ext.Button
|
getClassName
通過它的引用或實例返回類名稱:
1
|
Ext.getClassName(Ext.Button); //returns "Ext.Button"
|
Ext.Base
這是所有 Ext 類的基礎。所有的 Ext 類都繼承自 Ext.Base。該類所有的原型和靜態成員都會傳遞給繼承它的類。
Ext.Class
這是一個低級別的工廠類,用於通過 Ext.ClassManager 定義一個類。所以不應該在你的代碼中直接訪問;你應該使用 Ext.define。
Ext.ClassManager
它管理所有的類同時處理類反射。通常通過下面幾個方法訪問:
- define
- create
- widget
- getClass
- getClassName
在本章我們已經討論使用過這些方法。
Ext.Loader
用於動態的加載依賴。通常使用 Ext.require 來指定依賴。當你定義一個類時,這樣指定組件的依賴列表是一個很好的做法,如以下代碼所示:
1
|
Ext.require(['widget.window', 'layout.border','Ext.data.Connection']);
|
如果你需要引入一個指定命名空間下所有的 組件/類 時,使用通配符,如以下代碼所示:
1
|
Ext.require(['widget.*', 'layout.*', 'Ext.data.*');
|
使用以下語法排除掉不需要的類:
1
|
Ext.exclude('Ext.data.*').require('*');
|
用這種方式,依賴的類是異步加載的。如果在你定義的類中沒有指定依賴的類,那么當使用 Ext.Create 創建實例時,如果它是未加載的,這時將會同步加載這些類文件。這對性能有一定的影響,所以當你定義類時,使用 Ext.require 指定所需的類總是更好的。
- requires 屬性加載需要的類時,當前類初始化之前被加載。
- uses 屬性加載需要的類時,當前類初始化之后被加載。
singleton:true 屬性當前類初始化時,該實例是一個單例對象。
注意:定位類的文件路徑是基於類名的。例如:MyApp.view.About 類的路徑應該是 \myapp\view\ about.js 。
Events(事件)
一個事件可以是一個用戶操作,一個 Ajax 調用的響應等等。
Adding listeners(為類添加監聽)
當你創建對象或者創建以后都可以為這個對象添加監聽器。下列示例代碼為這個對象添加了一個 單擊事件 的監聽:
1
2
3
4
5
6
7
8
|
Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
listeners: {
click: function() {
Ext.Msg.alert('Button clicked!');
}
}
}) ;
|
你可以添加多個事件監聽,如以下代碼示例:
1
2
3
4
5
6
7
8
9
10
11
|
Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
listeners: {
mouseout: function() {
//Do something
},
click: function() {
// Do something
}
}
});
|
你也可以在對象創建之后,使用 on 方法為對象添加事件監聽:
1
2
3
4
|
var button = Ext.create('Ext.Button');
button.on('click', function() {
//Do something
}) ;
|
同樣的,你也可以使用 on 方法一次添加多個事件的監聽,如以下代碼示例:
1
2
3
4
5
6
7
8
9
|
var button = Ext.create('Ext.Button');
button.on({
mouseover: function() {
//Do something
},
mouseover: function() {
//Do something
}
}) ;
|
Removing listeners (刪除事件監聽)
You can also remove the listeners, but you need the reference to the function; you can’t use the anonymous function.
1
2
3
4
5
6
7
8
9
10
11
|
var HandleClick= function() {
Ext.Msg.alert('My button clicked!');
}
Ext.create('Ext.Button', {
listeners: {
click: HandleClick
}
}) ;
button.un('click', HandleClick);
|
頁面 DOM 元素的事件處理
你可以將監聽器添加到 DOM 元素,如下所示。
假設在你的 HTML 代碼中,有一個 div 元素 id=mydiv ,如以下代碼所示:
1
|
< div id="mydiv"></div >
|
用下列代碼為它添加事件監聽:
1
2
3
4
|
var div = Ext.get('mydiv');
div.on('click', function(e, t, eOpts) {
// Do something
});
|
訪問 DOM
有三種方法來訪問 DOM 元素:get,query,和 select 。
Ext.get
get 方法是根據這個 DOM 元素的 ID 檢索獲取並封裝為 Ext.dom.Element 對象:
1
|
var mydiv = Ext.get('myDivId');
|
Ext.query
這種方式基於傳入的 CSS 選擇器 從給定的根節點開始查找。它返回一個匹配選擇器的元素(HTMLElement[]/Ext.dom.Element[])數組。如果沒有匹配的,返回一個空值的數組對象。
在下面示例中,myCustomComponent.getEl().dom 是傳遞的根節點。Ext.query 將檢索這個節點內的子元素,並返回一個數組包含 CSS class 為 ‘oddRow‘ 的的元素:
1
|
var someNodes = Ext.query('.oddRow', myCustomComponent.getEl().dom);
|
Ext.select
給出一些 CSS/XPath 選擇器,Ext.select 方法返回一個 CompositeElement 類型的對象,代表一個元素的集合。
這個 CompositeElement 對象可以進行過濾,迭代,和對整個集合執行整體操作等等:
1
2
|
var rows = Ext.select('div.row'); ////Matches all divs with class
row rows.setWidth(100); // 這是設置所有元素的寬度為 100
|
你也可以用一行代碼,如下所示:
1
|
Ext.select('div.row').setWidth(100);
|
多重選擇器
在方法調用時通過指定多個搜索條件可以用來匹配多個元素:
1
|
Ext.select('div.row, span.title'); //匹配所有的 class 用 .row 的 div 元素,和匹配所有 class 用 .title 的 span 元素
|
選擇器 根
當你使用 select ,它默認取 HTML body 作為根並從默認的 body 開始檢索整個 DOM 樹。你可以通過制定一個根元素來避免這種情況,這樣它將只搜索給定的根的子節點。
1
|
Ext.get('myEl').select('div.row');
|
這兒使用了 ‘myEl’ 作為根節點。這將首先找到 id 為 ‘myEl’ 的元素,然后將在根元素(myEl)下面搜索出 class 為 ‘row’ 的 div 標簽。
1
|
Ext.select('div.row', true, 'myEl');// This is equivalent to the previous line.
|
鏈式選擇器
下列的查詢方式會匹配 class 為 row 並且 title 屬性值為 bar 的 div ,這個 div 屬於其父元素的首個子元素:
1
|
Ext.select('div.row[title=bar]:first')
|
Ext.ComponentQuery
這允許你用 ID,xtype,和 屬性查找一個組件。你可以全局搜索或者指定一個根組件。
下列查詢將返回所有的 xtype 為 button 的組件:
1
|
Ext.ComponentQuery.query('button');
|
得到一個 id 為 foo 的組件,用以下代碼:
1
|
Ext.ComponentQuery.query('#foo');
|
下列代碼將返回所有的 xtype 為 button 並且 title 屬性值為 my button 的組件:
1
|
Ext.ComponentQuery.query("button[title='my button']");; //or parent.query('textfield[title=my button]');
|
你也可以使用嵌套選擇器如下:You can also use nested selectors as follows:
1
|
Ext.ComponentQuery.query('formpanel numberfield'); // 這里獲取 xtype 為 frompanel 下面的 xtype 為 numberfield 的組件
|
下列代碼返回這個 parent 容器內匹配傳遞進來的選擇器的第一個直接子組件,如果沒有匹配上,返回 null 。
1
|
parent.child('button[itemId=save]');
|
同樣的,你也可以使用其他的方法,例如 nextNode, up, down, previousSibling 等等。
組件,容器,和布局
Ext JS 提供了一組豐富的組件和布局,這使在 Ext JS 中開發 UI 變得超級簡單,甚至非專業 UI 開發人員也能夠輕易的使用。
組件
從簡單的組件說起,例如 button 和 label ,到復雜的組件,例如 Tree Panel,Grids 等等,Ext JS 有大量的內置組件。所有的組件都派生自Ext.Component 類,它提供支持創建,重繪,渲染和處理組件。
所有的組件都有一個屬性叫做 xtype 。它是非常有用的,它用在當你不想馬上實例化這個組件時,而是想讓這個組件在實際被應用時才創建,就是我們俗稱的懶加載。
容器
容器是一個特殊的組件類型,它能夠持有其他組件。在 Ext JS 中 Ext.container.Container 類是所有的容器的基礎類。
Ext.toolbar.Toolbar, Ext.panel.Panel, 和 Ext.Editor 是一些內置組件。這些組件都是可以包含其他組件。而像 Ext.button.Button 類就不是派生自Ext.container.Container ,所以它不能夠包含其他組件。
一個典型的 Ext JS 應用包含一組嵌套的組件。看下面這個例子並思考:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
Ext.create('Ext.panel.Panel', {
renderTo:Ext.getBody(),
width:700,
height:400,
items:[{
xtype: 'panel',
title: 'Panel 1',
},{
xtype: 'panel',
title: 'Panel 2',
height: 200,
items: [{
xtype: 'button',
text: 'Click Me'
}]
},{
xtype: 'panel',
title: 'Panel 3',
width: 150,
height: 100
}]
});
|
在前面的代碼中,這是嵌套的組件,結構如下圖所示:
上面的代碼運行后將輸出類似以下截圖:
布局
布局定義了包含的組件是如何定位的以及設定組件的尺寸大小。每一個容器都有一個布局。默認布局是 auto 。這將不會為子組件指定任何關於位置和大小的規則。
在上面的圖中,你可能已經注意到這些子組件只是一個接一個嵌套在父級容器中。這是在代碼中因為我們還沒有為這些組件制定任何布局,默認情況下使用的是 auto 布局。
現在,讓我們在相同的代碼里使用一些布局。下列示例中,我們將使用 column 布局和 center 布局。
當你使用 column 布局,你可以指定 columnWidth 。所有的列的 columnWidth 的值的總和必須等於 1 。你也可以為一些列指定固定寬度,如以下代碼所示。這里,Panel3 取了一個 150 的固定寬度,然后剩下的兩列按照 columnWidth 的值分配剩下的寬度:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
Ext.create('Ext.panel.Panel', {
renderTo:Ext.getBody(),
width:700,
height:400,
layout:'column',
items: [{
xtype: 'panel',
title: 'Panel 1',
columnWidth: 0.4,
height: 400,
},{
xtype: 'panel',
title: 'Panel 2',
columnWidth: 0.6,
layout: 'center',
height: 400,
items: [{
xtype: 'button',
text: 'Click Me'
}]
},{
xtype: 'panel',
title: 'Panel 3',
width: 150,
height: 400
}]
});
|
以上代碼輸出為:
updateLayout
updateLayout 是 Ext.container.Container 對象里的一個方法。這可以用來根據布局規則重新定位子組件。例如你修改了布局方式,需要動態的更新布局時。
suspendLayout
大多數時候你不會用到這個 updateLayout 方法,然而有些時候你必須調用它。
這個 updateLayout 方法是在你重繪和當你添加或刪除了一個組件時自動調用。有時候你可能需要它暫停一下,不是馬上就調用,特別是當你添加或刪除多個子組件時。所以在這種情況下,你可以設置 suspendLayout 屬性為 true ,一旦你完成添加或刪除組件的操作,你可以設置 suspendLayout 為 false 並在你的代碼中手動調用 updateLayout 方法。
同樣的如果你想對整個框架停止更新布局,你可以調用 Ext.suspendLayouts() ,然后在你的操作完成后你可以通過調用 Ext.resumeLayouts(true) 恢復它。
以下是 Ext JS 中可用的布局:
- absolute
- accordion
- anchor
- border
- card
- center
- column
- fit
- hbox
- table
- vbox
absolute 絕對布局
這個布局使用 x 和 y 屬性來指定組件的絕對定位:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
Ext.create('Ext.panel.Panel', {
renderTo:Ext.getBody(),
width:700,
height:400,
layout:'absolute',
items: [{
xtype: 'panel',
title: 'Panel 1',
x: 12,
y: 20,
height: 250
},{
xtype: 'panel',
title: 'Panel 2',
x: 200,
y: 150,
height: 200
},{
xtype: 'panel',
title: 'Panel 3',
x: 400,
y: 250,
width: 150,
height: 100
}]
});
|
這里所示的輸出,你可以重疊組件因為他們用絕對位置定位的:
accordion 手風琴(可折疊)布局
這個布局展示了在一個時間里只有一個內置的可支持折疊和展開的子級 panel 。瞧一下以下示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout: 'accordion',
items: [{
title: 'Item 1',
html: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum'
},{
title: 'Item 2',
html: 'some content here'
},{
title: 'Item 3',
html: 'empty'
}]
});
|
這里顯示的輸出,這個 Item 1 是展開的,而其他的 panel 是折疊的:
anchor 錨點布局
這個布局使你能夠指定子級組件的大小,而這是相對於布局容器的。首先容器根據指定的錨點規則調整然后所有的子級組件再作調整:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout: 'anchor',
items: [{
title: 'Item 1',
html: 'Item 1',
anchor: '50%'
},{
title: 'Item 2',
html: 'Item 2',
anchor: '-20 -200'
},{
title: 'Item 3',
html: 'Item 3',
anchor: '-200'
}]
});
|
輸入如以下截圖:
border 布局
這個布局允許你為子組件指定一個區域位置,例如 center,north,south,west 和 east。當你使用 border 布局時,在其內的組件必須有一個指定區域為 center,如下列代碼所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout: 'border',
items: [{
title: 'Item 1',
html: 'Item 1',
region: 'center'
},{
title: 'Item 2',
html: 'Item 2',
region: 'east',
width: 200
},{
title: 'Item 3',
html: 'Item 3',
region: 'south',
height: 100
}]
}) ;
|
以上代碼輸出類似下列視圖:
card 卡片布局
在此布局中,只有一個子組件是可見的,這個組件基本上充滿整個容器。卡片布局一般應用在向導或者 tabs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout: 'card',
defaultListenerScope: true,
bbar: ['->',{
itemId: 'btn-prev',
text: 'Previous',
handler: 'showPrevious',
disabled: true
},{
itemId: 'btn-next',
text: 'Next',
handler: 'showNext'
}],
items: [{
index: 0,
title: 'Item 1',
html: 'Item 1'
},{
index: 1,
title: 'Item 2',
html: 'Item 2'
},{
index:2,
title: 'Item 3',
html: 'Item 3'
}],
showNext: function () {
this.navigate(1);
},
showPrevious: function () {
this.navigate(-1);
},
navigate: function (incr) {
var layout = this.getLayout();
var index = layout.activeItem.index + incr;
layout.setActiveItem(index);
this.down('#btn-prev').setDisabled(index===0);
this.down('#btn-next').setDisabled(index===2);
}
});
|
卡片布局的輸出。當你點擊 next 按鈕,將會顯示 Item 2 面板:
center 中心布局
這種布局,容器的子組件在中間。在本章中開始介紹布局的部分,我們已經有一個例子了。
column 列布局
用此布局,你可以將容器划分為指定數量的列並指定每列所占的大小。這個例子也在本章開始介紹布局的部分中可以找到。
fit 適配布局
在此布局中,子組件將會自適應容器的尺寸。如下:
1
2
3
4
5
6
7
8
9
10
11
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout: 'fit',
bodyPadding: 20,
items: [{
title: 'Item 1',
html: 'Fills the container',
}]
});
|
下列截圖展示以上代碼的輸出。注意:Item 1 組件與父級容器之間的空隙是我們指定了 bodyPadding 屬性:
hbox 布局
這種布局與 column 布局幾乎是一樣的,但是這種布局允許你拉伸列的高度。這里使用 flex 選項為子組件設置水平的相對值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout:{
type: 'hbox',
pack: 'start',
align: 'stretch',
},
items: [{
title: 'Item 1',
html: 'Item 1',
flex: 1
},{
title: 'Item 2',
html: 'Item 2',
width: 100
},{
title: 'Item 3',
html: 'Item 3',
flex: 2
}]
});
|
上面代碼輸出:
table 表格布局
這個布局允許你渲染一個表格出來。你可以指定列數和行數,使用 rowspan 和 colspan 創建復雜布局:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout:{
type: 'table',
columns: 3,
tableAttrs: {
style: {
width: '100%'
}
}
},
items: [{
rowspan: 3,
title: 'Item 1',
html: 'Item 1'
},{
title: 'Item 2',
html: 'Item 2'
},{
title: 'Item 3',
rowspan: 2,
html: 'Item 3'
},{
title: 'Item 4',
html: 'Item 4'
},{
title: 'Item 5',
html: 'Item 5'
},{
title: 'Item 6',
html: 'Item 6'
},{
title: 'Item 7',
html: 'Item 7'
}]
});
|
以下截圖所示為前面 table 布局代碼的輸出結果:
VBox 布局
這個布局內,子組件是垂直向下一個接一個排列。看一下以下的示例代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
width: 700,
height: 400,
layout:{
type: 'vbox',
pack: 'start',
align: 'stretch',
},
items: [{
title: 'Item 1',
html: 'Item 1',
flex: 1
},{
title: 'Item 2',
html: 'Item 2',
height: 100
},{
title: 'Item 3',
html: 'Item 3',
flex: 2
}]
});
|
這段代碼所示的輸出:
總結
在本章中,我們了解學習了在 Ext JS 中的基礎類和這些類中常用的方法,你還學習了如何創建和擴展一個類。還有如何使用 事件 和 查詢元素及組件的功能。
本人喜交朋友,歡迎掃描博客公告處個人二維碼交流進步