Ext JS 6學習文檔-第3章-基礎組件
基礎組件
在本章中,你將學習到一些 Ext JS 基礎組件的使用。同時我們會結合所學創建一個小項目。這一章我們將學習以下知識點:
- 熟悉基本的組件 – 按鈕,文本框,日期選擇器等等
- 表單字段的校驗
- 菜單和工具欄
- 設計一個表單
- 計算器程序– 本章的示例項目
本章的主要目的是創建一個表單設計和一個計算器示例項目。以下圖分別展示了表單設計和計算器設計。
首先,你觀察下列表單設計,你會發現我們使用了大量的控件,例如 label 和文本框。
以下圖展示了表單的設計:
繼續,設計計算器程序大量的使用了按鈕控件。所以你首要學習的是按鈕和 handler 。隨后在本章最后我們將會構建一個 計算器程序。在這個過程中,你會知道如何使 view(視圖) 和 controller(控制器)進行交互並協同工作。我們還將看到如何綁定 view model(視圖模型) 的屬性到一個 view(視圖) 的字段上。
下圖為計算機的設計展示:
熟悉基本組件
Ext JS 有大量的優秀的控件,現在讓我們開始認識這些基礎的組件吧。
Ext.Button
這是一個很常用的控件;handler 是用於處理單擊事件,如以下代碼所示:
1
2
3
4
5
6
7
|
Ext.create('Ext.Button', {
text: 'My Button',
renderTo: Ext.getBody(),
handler: function() {
alert('click');
}
});
|
前面代碼的輸出:
我在第二章已經介紹過如何運行樣例代碼,但這里我還想再次重申這一點,此文檔中的大部分樣例代碼都是可以直接運行的。你可以選擇在你本地設備上或者在 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!');
}
}) ;
|
現在粘貼下列的創建按鈕的樣例代碼,運行並查看結果:
1
2
3
4
5
6
7
8
9
10
11
12
|
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('Ext.Button', {
text: 'My Button',
renderTo: Ext.getBody(),
handler: function() {
alert('click');
}
});
}
});
|
- 不是所有的代碼都可以這樣運行,此外並非所有的示例代碼都會有視覺呈現。
你還可以使用 listeners 配置添加更多的事件處理器,如以下代碼所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
Ext.create('Ext.Button', {
text: 'My Button',
renderTo: Ext.getBody(),
listeners: {
click: {
fn: function(){
//Handle click event
alert('click');
}
},
mouseout: {
fn: function(){
//Handle double click event
alert('Mouse out');
}
}
}
});
|
以上代碼只是創建了一個簡單的按鈕,你還可以創建很多不同的按鈕,有 link button(連接按鈕),menu button(菜單按鈕),toggle button(開關按鈕) 等等;
來創建一個鏈接按鈕,設置 href 屬性,如以下代碼所示:
1
2
3
4
5
|
Ext.create('Ext.Button', {
renderTo: Ext.getBody(),
text: 'Link Button',
href: 'http://www.sencha.com/'
});
|
上面創建的鏈接按鈕輸出如圖。當點擊它則打開鏈接:
通過設置 menu 屬性,創建一個菜單按鈕,如以下代碼所示:
1
2
3
4
5
6
7
8
9
10
11
|
Ext.create('Ext.Button', {
text: 'My Button',
renderTo: Ext.getBody(),
menu: [{
text: 'Item 1'
}, {
text: 'Item 2'
}, {
text: 'Item 3'
}]
});
|
輸出如下,當點擊時出現下拉菜單:
Ext.Button 還有許多屬性,例如 bind, cls, disabled,html,tooltip,tpl 等等,你可以根據自己需求使用。
Ext.MessageBox
Ext.window.MessageBox 類提供了 message box 實現。Ext. MessageBox 是一個單例對象。你可以使用 MessageBox 彈出一個警告,信息確認,提示輸入等等。
下列代碼將彈出一個簡單的提示信息。這里解釋一下 Ext.Msg 是 Ext. Messagebox 類的別名:
1
|
Ext.Msg.alert('Info', 'Document saved!');
|
下列代碼將彈出一個消息確認框,button 為選擇的值,取 yes 或 no :
1
2
3
4
5
6
7
|
Ext.Msg.confirm('Confirm', 'Are you want to cancel the updates?', function(button){
if('yes'==button) {
} else {
}
});
|
你也可以自定義這個 message box 如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Ext.MessageBox.show({
title:'Save Changes?',
msg: 'Do you want to save the file?',
buttons: Ext.MessageBox.YESNO,
fn: function(button){
if('yes'==button){
}else if('no'==button){
}
},
icon: Ext.MessageBox.QUESTION
}) ;
|
上面代碼輸出如下:
表單和表單字段
現在我們看一下都有哪些表單相關的組件。
Ext.form.Panel
這個 form panel (表單面板)繼承自 panel 並添加了表單相關的功能,例如字段管理,校驗,提交等等。form panel 的默認布局是 anchor layout ,但是如果需要你可以改變這個配置。
form panel 有一個很方便的配置為 fieldDefaults,它可以用於指定表單內所有字段的默認類型。
fields (字段/表單域)
Ext JS 提供了很多內置的表單字段。比較常用的一些字段:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
Ext.form.field.Checkbox
Ext.form.field.ComboBox
Ext.form.field.Date
Ext.form.field.File
Ext.form.field.Hidden
Ext.form.field.HtmlEditor
Ext.form.field.Number
Ext.form.field.Radio
Ext.form.field.Text
Ext.form.field.TextArea
Ext.form.field.Time
|
我們看一下其中的一些字段的應用。
Ext.form.field.Text
這是一個基本的文本框,它具有很多有用的屬性和配置。其中有一個很有用的屬性是 vtype 它是用於校驗的。 例如以下代碼,這個 vtype 屬性為 email 用於驗證輸入內容是否是有效的電子郵箱:
1
2
3
4
5
6
7
|
Ext.create('Ext.form.field.Text', {
renderTo: Ext.getBody(),
name: 'email',
fieldLabel: 'Email',
allowBlank: false,
vtype: 'email'
});
|
這里 allowBlank 也是一個校驗屬性。通過設置 allowBlank 屬性為 false ,如果這個字段為空白,將會提示校驗不通過。
Ext.form.field.Number
number 字段繼承自 spinner 字段,spinner 字段則繼承自 text 字段,進而的 number 等於是繼承了兩者。這個 number 字段提供了幾個選項來處理數值。下列代碼創建了一個數值文本框:
1
2
3
4
5
6
7
8
|
Ext.create('Ext.form.field.Number', {
renderTo: Ext.getBody(),
name: 'Count',
fieldLabel: 'Count',
value: 0,
maxValue: 10,
minValue: 0
});
|
你可以移除下拉按鈕,方向鍵,鼠標滾輪監聽,用配置:hideTrigger, keyNavEnabled,和 mouseWheelEnabled 。
Ext.form.field.ComboBox
下列代碼創建了一個月份下拉菜單。這個 combobox 有一個配置為 store。 這個 store 是數據源,為此下拉菜單提供數據。store 是屬於 ExtJS 中數據包部分, 在接下來的章節中我們會詳細介紹的。
combobox 中另一個重要的配置是 queryMode 。這個屬性取值可以是 ‘local’ 或者 ‘remote’。如果你設置為 remote 了,那么這個數據源 store 將在運行加載數據時發送請求從遠程服務器獲取數據:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
var months = Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
data: [{"abbr":"JAN", "name":"January"},
{"abbr":"FEB", "name":"February"},
{"abbr":"MAR", "name":"March"},
{"abbr":"APR", "name":"April"},
{"abbr":"MAY", "name":"May"},
{"abbr":"JUN", "name":"June"},
{"abbr":"JUL", "name":"July"},
{"abbr":"AUG", "name":"August"},
{"abbr":"SEP", "name":"September"},
{"abbr":"OCT", "name":"October"},
{"abbr":"NOV", "name":"November"},
{"abbr":"DEC", "name":"December"}]
}) ;
Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Choose Month',
store: months,
queryMode: 'local',
displayField: 'name',
valueField: 'abbr',
renderTo: Ext.getBody()
});
|
以上代碼的輸出如下:
Ext.form.field.HtmlEditor
Ext JS 也有一個非常優秀的 HTML 編輯器,它提供直接在 web 頁面上處理文字的能力,如以下代碼所示:
1
2
3
4
5
|
Ext.create('Ext.form.HtmlEditor', {
width: 800,
height: 200,
renderTo: Ext.getBody()
});
|
以上代碼輸出如下:
表單字段的校驗
大多數表單都有自己的校驗規則,例如你鍵入了一個非數值的內容到 number 字段,它將顯示一個驗證無效的提示。再有這個 text 字段(文本框) 校驗屬性有 allowBlank,minLength,和 maxLength 。 更進一步的,還有 regex 屬性可以使用正則表達式自定義校驗。
form panel 的事件
form panel 支持的部分事件:
- beforeaction: 任意動作執行前觸發,例如 submit,load,doAction 這些動作執行時
- actionfailed: 執行一個動作失敗時觸發
- actioncomplete: 在一個動作執行完成之后觸發This event will be fired after an action is completed
- validitychange: 表單鍵入的內容有效性發生變化時觸發
- dirtychange: 表單的dirty狀態改變時觸發
表單字段容器
以下是一些 from panel 里很有用的容器。
Ext.form.CheckboxGroup
CheckboxGroup 繼承自 FieldContainer 用於組織復選框。下列示例中,復選框組的 items 中所有的項都有相同的 name ;這有助於將得到的值作為一個單一的參數傳遞給服務器。
1
2
3
4
5
6
7
8
9
10
|
Ext.create('Ext.form.CheckboxGroup', {
renderTo: Ext.getBody(),
fieldLabel: 'Skills ',
vertical: true,
columns: 1,
items: [{ boxLabel: 'C++', name: 'rb', inputValue: '1' },
{ boxLabel: '.Net Framework', name: 'rb', inputValue: '2', checked: true },
{ boxLabel: 'C#', name: 'rb', inputValue: '3' },
{ boxLabel: 'SQL Server', name: 'rb', inputValue: '4' }]
}) ;
|
以上代碼輸出如下:
Ext.form.FieldContainer
FieldContainer 是很有用的,當你想將一組相關字段附加到一個標簽時。
以下代碼的輸出你會發現一個 label 后面綁定了兩個文本框:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
Ext.create('Ext.form.FieldContainer', {
renderTo: Ext.getBody(),
fieldLabel: 'Name',
layout: 'hbox',
combineErrors: true,
defaultType: 'textfield',
defaults: {
hideLabel: 'true'
},
items: [{
name: 'firstName',
fieldLabel: 'First Name',
flex: 2,
emptyText: 'First',
allowBlank: false
}, {
name: 'lastName',
fieldLabel: 'Last Name',
flex: 3,
margin: '0 0 0 6',
emptyText: 'Last',
allowBlank: false
}]
});
|
Ext.form.RadioGroup
RadioGroup 繼承自 CheckboxGroup 用於組織單選按鈕。items 中的項都有相同的 name,另外這是單選的,如以下代碼所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Ext.create('Ext.form.RadioGroup', {
renderTo: Ext.getBody(),
fieldLabel: 'Sex ',
vertical: true,
columns: 1,
items: [{
boxLabel: 'Male',
name: 'rb',
inputValue: '1'
},{
boxLabel: 'Female',
name: 'rb',
inputValue: '2'
}]
});
|
代碼輸出:
提交表單
使用 form 的 submit 方法提交表單。使用 getForm 方法獲取表單並 isValid 方法進行提交前的表單內容校驗。如以下代碼所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var form = this.up('form').getForm();
if (form.isValid()) {
form.submit({
url: 'someurl',
success: function () {
},
failure: function () {
}
});
} else {
Ext.Msg.alert('Error', 'Fix the errors in the form')
}
|
菜單和工具欄
對於你能想到的任何的菜單和工具欄 Ext JS 提供了最完整的支持。Ext.toolbar.Toolbar 用於構建一個工具欄。默認情況下任何子項在Ext.toolbar.Toolbar 都是按鈕,但是你可以添加任意控件進去,例如一個文本框,一個數值框,一個圖標,一個下拉菜單等等。
規范整理你的工具欄中的項,你可以使用 空格(Ext.toolbar.Spacer), 分隔符(Ext.toolbar. Separator),和 使控件右對齊(Ext.toolbar.Fill) 。這里也可以使用快捷方式 ‘ ‘ (空格),’-‘ 和 ‘|’ (都是分隔符,只有很小的差別),和 ‘->‘ (右對齊)。
Ext.menu.Menu 用於構建一個菜單,items 屬性中為 Ext.menu.Item 一個個菜單項。
一個簡單的代碼示例和以下截圖的輸出:
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
44
45
46
|
Ext.create('Ext.toolbar.Toolbar', {
renderTo: Ext.getBody(),
width: 800, items: [{
text: 'My Button'
},{
text: 'My Button',
menu: [{
text: 'Item 1'
}, {
text: 'Item 2'
}, {
text: 'Item 3'
}]
},{
text: 'Menu with divider',
tooltip: {
text: 'Tooltip info',
title: 'Tip Title'
},
menu: {
items: [{
text: 'Task 1',
// handler: onItemClick
}, '-', {
text: 'Task 2',
// handler: onItemClick
}, {
text: 'Task 3',
// handler: onItemClick
}]
}
},'->',{
xtype: 'textfield',
name: 'field1',
emptyText: 'search web site'
},'-','Some Info',{
xtype: 'tbspacer'
},{
name: 'Count',
xtype: 'numberfield',
value: 0,
maxValue: 10,
minValue: 0,
width: 60
}]
});
|
設計一個(客戶反饋)表單
現在根據之前所學,我們來設計一個表單。
我們將設計如圖所示的表單:
以下是這個表單的代碼。這里我維護着一個這個例子的完整的源碼 https://github.com/ananddayalan/extjs-by-example-customer-feedback-form
這里我們所有的組件都在 Viewport 中。 這是一個專用的容器,它代表瀏覽器里應用的視圖區域。
在 Viewport 中我們設置 scrollable 選項將子組件設為滾動的,使用 true 或 false 。也可以取值為 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
Ext.create('Ext.container.Viewport', {
scrollable: true,
items: [{
xtype: 'container',
layout: {
type: 'hbox',
align: 'center',
pack: 'center'
},
items: [ {
xtype: 'form',
bodyPadding: 20,
maxWidth: 700,
flex: 1,
title: 'Custom Feedback',
items:[{
xtype: 'fieldcontainer',
layout: 'hbox',
fieldLabel: 'Name',
defaultType: 'textfield',
defaults: {
allowBlank: false,
flex: 1
},
items: [{
name: 'firstName',
emptyText: 'First Name
}, {
name: 'lastName',
margin: '0 0 0 5',
emptyText: 'Last Name'
}]
},{
xtype: 'datefield',
fieldLabel: 'Date of Birth',
name: 'dob',
maxValue: new Date() /* Prevent entering the future date.*/
}, {
fieldLabel: 'Email Address',
name: 'email',
vtype: 'email',
allowBlank: false
}, {
fieldLabel: 'Phone Number',
labelWidth: 100,
name: 'phone',
width: 200,
emptyText: 'xxx-xxx-xxxx',
maskRe: /[\d\-]/,
regex: /^\d{3}-\d{3}-\d{4}$/,
regexText: 'The format must be xxx-xxx-xxxx'
},{
xtype: 'radiogroup',
fieldLabel: 'How satisfied with our service?',
vertical: true,
columns: 1,
items: [ {
boxLabel: 'Very satisfied',
name: 'rb',
inputValue: '1'
}, {
boxLabel: 'Satisfied',
name: 'rb', inputValue: '2'
}]
},{
xtype: 'checkboxgroup',
fieldLabel: 'Which of these words would you use to describe our products? Select all that apply',
vertical: true,
columns: 1,
items: [{
boxLabel: 'Reliable',
name: 'ch',
inputValue: '1'
}]
},{
xtype: 'radiogroup',
fieldLabel: 'How likely is it that you would recommend this company to a friend or colleague?',
vertical: false,
defaults: { padding: 20 },
items: [ {
boxLabel: '1',
name: 'recommend',
inputValue: '1'
}],
buttons: [{
text: 'Submit',
handler: function () {
var form = this.up('form').getForm();
if (form.isValid()) {
form.submit({
url: 'cutomer/feedback',
success: function () {},
failure: function () {}
});
} else {
Ext.Msg.alert('Error', 'Fix the errors in the form')
}
}
}]
}]
}]
}]
});
|
在以上代碼中通過在容器級設置 defaultType 屬性,這樣我們就可以不必在容器的每個子組件里重復的指定 xtype 屬性了。這樣默認情況下,所有子組件在沒有顯式指定 xtype 時默認的類型都是 textfield 。
form panel 上有一個 flex 配置用於填補父容器的寬度,同時通過設置 maxWidth 為 700 限制 form panel 的最大寬度。
字段容器使用 hbox 布局將 first name 和 last name 文本框放在一個 label 標簽下。
寫一個計算器應用
現在我們結合目前所學構建一個完整的小項目。這是我們將要構建的計算器的設計:
文件夾結構
這是我們創建的計算器工程的目錄結構。這里我不是用 sencha Cmd 生成的項目,只是從 Ext JS 復制了一些必須的文件到項目文件夾中:
完整可用的項目在這里: https://github.com/ananddayalan/extjs-by-example-calculator.
App – app.js
在 app.js 文件里我們簡單的創建了 Main 視圖,作為可移動窗體浮動在瀏覽器:
1
2
3
4
5
6
|
Ext.application({
name: 'Calc',
launch: function () {
Ext.create('Calc.view.main.Main').show();
}
});
|
再談 MVC 和 MVVM
第一章的時候,我們已經介紹過 MVC (Model View Controller) 和 MVVM (Model View ViewModel)。 這個示例項目的代碼很好的展示了 視圖,控制器,和視圖模型之間的區別。
Model (模型)
這代表着數據層。model 保存的數據可以包含數據驗證和邏輯。
View (視圖)
這一層是用戶界面。包含有 button,form,和 message box 等等組件。在我們這次寫的計算器應用中 main.js 就是一個很好的視圖例子。
Controller (控制器)
控制器處理 view(視圖)相關的邏輯,例如 view 的 event(事件)處理,還有任何程序相關邏輯都可以寫在這里。
ViewController (視圖控制器) 和 Controller (控制器)
在 Ext JS 5 和 6 中,有兩種類型的控制器:ViewController 和 Controller。 這個 ViewController 自 Ext JS 5 開始引進的。ViewController 是為一個指定的視圖創建的控制器,但是這個控制器也可以交叉其他視圖的邏輯。
ViewController 帶來了一些新的概念,例如 引用和監聽,簡化視圖與控制之間的關系。同時 View 銷毀時 ViewController 也會被銷毀,他們具有相同的生命周期,在這個例子中我們沒有使用 引用和監聽,但是在下一個例子中我們會使用的。
- 你可以使用 listeners 代替 handler 處理事件
View model
view model 封裝了 view(視圖)所需要的展示邏輯,綁定數據到 view 並且每當數據改變時處理更新。
它有別於 model ,view model 主要是為一個指定的視圖而創建的。一個 model 是一個純粹的數據類並可用於整個應用中,但一個 view model 是起到一個 view 和 model 之間的數據粘合劑的作用。看一下 main.js 的 視圖模型綁定。
視圖 — Main.js
這里我為這個計算器應用創建一個視圖為 Main 。這個視圖里包含所有的按鈕,顯示字段等等。相關的事件用 controller 的方法。這個視圖的控制器已經使用 controller 配置指定了。
這個視圖使用 table 布局,配置為 4 列。CSS 類使用 cls 屬性指定。
代碼里有附加的注釋:
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
Ext.define('Calc.view.main.Main', {
extend: 'Ext.window.Window',
/* 表示在當前視圖加載之前先加載這些所需的類*/
requires: [ 'Calc.view.main.MainController',
'Calc.view.main.MainModel'],
xtype: 'app-main',
controller: 'main',
/* 視圖的 view model (視圖模型)*/
viewModel: { type: 'main' },
resizable: false,
layout: {
type: 'table',
columns: 4
},
/* defaultType 和 defaults 屬性是用於 items 內的子組件的,任何子組件都可以覆蓋這些配置 */
defaultType: 'button',
defaults: {
width: 50,
height: 50,
cls: 'btn',
handler: 'onClickNumber'
},
/* 這里我用 Ext.window.Window 的 header 顯示計算器的結果。使用 header 你可以在瀏覽器里移動這個計算器。*/
header: {
items: [{
xtype: 'displayfield',
colspan: 4,
width: 200,
cls: 'display',
bind: {
value: '{display}'
},
height: 60,
padding: 0
}]
},
items: [{
text: 'C',
colspan: 2,
width: 100,
cls: 'btn-green',
handler: 'onClickClear'
}, {
text: '+/-',
cls: 'btn-green',
handler: 'onClickChangeSign'
}, {
text: '÷',
cls: 'btn-orange',
handler: 'onClickOp'
},{
text: '7'
},{
text: '8'
},{
text: '9'
},{
text: '×',
cls: 'btn-orange',
handler: 'onClickOp'
},{
text: '4'
},{
text: '5'
},{
text: '6'
},{
text: '-',
cls: 'btn-orange',
handler: 'onClickOp'
},{
text: '1'
},{
text: '2'
},{
text: '3'
},{
text: '+',
cls: 'btn-orange',
handler: 'onClickOp'
},{
text: '0',
width: 100,
colspan: 2
},{
text: '.',
handler: 'onClickDot'
},{
text: '=',
cls: 'btn-orange',
handler: 'onClickOp'
}]
});
|
控制器 — MainController.js
雖然這個控制器的代碼有點長,這是一個非常簡單的代碼。控制器中有很多方法處理按鈕的點擊事件,例如運算符和操作數的點擊處理。控制器使用了一個 model 為 Main :
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
Ext.define('Calc.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
views: ['Calc.view.main.Main'],
models: ['Main'],
//這個 state 是一個自定義屬性,用來跟蹤計算器的狀態。
state: {
operatorClicked: false,
selectedOperator: null,
dotClicked: false,
op1: 0,
numberClicked: false,
sign: true,
decimal: false
},
onClickClear: function () {
var vm = this.getViewModel();
vm.set('display','0');
this.state.selectedOperator=null;
this.state.op1=0;
this.state.isPositive = true;
this.state.decimal = false;
this.state.sign = true;
},
onClickChangeSign: function (btn) {
var vm = this.getViewModel();
var cur = vm.get('display');
if(cur!='0') {
if(this.state.sign===true ) {
vm.set('display', '-' + cur);
}else {
vm.set('display', cur.toString().substring(1));
}
}
this.state.sign=!this.state.sign;
},
onClickOp: function (btn) {
if(this.state.selectedOperator!=null && this.state.numberClicked===true){
var vm = this.getViewModel();
var op2 = parseFloat(vm.get('display'));
var op1 = parseFloat(this.state.op1);
var result = 0;
switch(this.state.selectedOperator){
case '+':
result = op1 + op2;
break;
case '-':
result = op1 - op2;
break;
case '×':
result = op1 * op2;
break;
case '÷':
result = op1 / op2;
break;
}
vm.set('display', Math.round(result * 100) / 100);
this.state.selectedOperator=null;
}
if(btn.text!='=') {
this.state.operatorClicked = true;
}
this.state.selectedOperator = btn.text;
this.state.numberClicked = false;
},
onClickDot: function (btn) {
if(this.state.decimal===false) {
var vm = this.getViewModel();
vm.set('display', vm.get('display') + '.');
}
},
onClickNumber: function (btn) {
this.state.numberClicked = true;
if(this.state.selectedOperator ==='='){
this.onClickClear();
}
var vm = this.getViewModel();
if(this.state.operatorClicked===true) {
this.state.op1= vm.get('display');
vm.set('display', btn.text);
this.state.operatorClicked=false;
}else{
var cur = vm.get('display');
if(cur == '0') {
cur = '';
}
vm.set('display', cur + btn.text);
}
}
});
|
視圖模型 — MainViewModel.js
這個 ViewModel 只有一個屬性為 display 。這個用來綁定到計算器顯示的值上。這里我們不會分別用一組字段創建模型,此外我們還將會硬編碼數據。
1
2
3
4
5
6
7
|
Ext.define('Calc.view.main.MainModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.main',
data: {
display: 0.0
}
});
|
在即將到來的章節中你將學習更多關於 模型,視圖模型,字段,字段類型,校驗 等等。
總結
在本章中,你了解了不同的基本組件,例如 文本框,數字框,按鈕,菜單等等。你已經學會如何使用表單字段設計一個表單和我們之前創建了一個簡單的計算器項目。
本人喜交朋友,歡迎掃描博客公告處個人二維碼交流進步