Sencha提供了免費(fèi)的Cmd工具陕习,可以用來創(chuàng)建Ext JS項(xiàng)目并提供了一些便利的功能危纫。
Sencha也在官方文檔中提供了一個(gè)示例來演示如何創(chuàng)建一個(gè)Sample Login App。
本文就介紹一下這個(gè)官網(wǎng)示例状蜗。
準(zhǔn)備工作
- 下載Sencha Ext JS的SDK,本文中使用的是開源的GPL的6.0.1版本
- 下載Sencha Cmd,這個(gè)是免費(fèi)的勾习,本文中使用的是Windows 64-bit帶JRE的6.1.2版本
一些廢話:
也許Sencha是為了更好地推它的商用版本吧,從6.0.0版本開始懈玻,就把GPL版本的下載位置藏的很深巧婶,而且還需要通過發(fā)送郵件的方式來提供下載。
安裝
- SDK解壓縮放到一個(gè)指定目錄涂乌,本文中為D:\ext-6.0.1
- Cmd安裝到默認(rèn)位置即可
一些廢話:
6.x版本從以前方便很多艺栈,如果你使用的是5.x版本,那還需要額外安裝JDK, ANT, Ruby, SASS, COMPASS湾盒,這里就不啰嗦了湿右。
本文創(chuàng)建的示例項(xiàng)目的路徑為D:\TutorialApp
那我們開始創(chuàng)建程序吧。
打開cmd命令行罚勾,使用sencha [-sdk SDK所在目錄] generate app [-classic|-modern] AppName App目錄命令來創(chuàng)建項(xiàng)目毅人。
sencha -sdk D:\ext-6.0.1 generate app -classic TutorialApp D:\TutorialApp
- -sdk D:\ext-6.0.1指明Ext JS SDK的所在目錄吭狡,如果運(yùn)行命令行的所在目錄就是SDK目錄(D:\ext-6.0.1),則可以省略
- -classic|-modern可以省略丈莺,Ext JS的6.0版本其中一個(gè)主要的更新就是把Ext JS和Touch合并划煮,在創(chuàng)建時(shí)可以選擇哪一種類型,classic對(duì)應(yīng)Ext JS缔俄,而modern對(duì)應(yīng)Touch般此。如果省略,則創(chuàng)建所謂的universal類型牵现,即classic和modern并存铐懊。在本文中演示的是桌面端程序,所以我們選擇classic瞎疼。
- TutorialApp是項(xiàng)目名稱科乎,也將作為該項(xiàng)目的namespace。
- D:\TutorialApp是項(xiàng)目名錄
一些廢話:
運(yùn)行命令后贼急,可以去倒一杯水茅茂,起來活動(dòng)活動(dòng),因?yàn)檫@個(gè)過程大概會(huì)持續(xù)幾分鐘太抓。完成之后空闲,看下TutorialApp目錄的大小,會(huì)發(fā)現(xiàn)大概500M走敌,真夠大的碴倾。
從命令進(jìn)入項(xiàng)目目錄D:\TutorialApp,并輸入命令sencha app watch
cd D:\TutorialApp
sencha app watch
一些廢話:
運(yùn)行命令后掉丽,可以再起來活動(dòng)活動(dòng)跌榔。
sencha app watch會(huì)啟動(dòng)內(nèi)置的jetty服務(wù)器,可以使我們方便地通過http://localhost:1841/ 來查看頁面捶障。而且watch會(huì)監(jiān)聽項(xiàng)目目錄中的文件變化而自動(dòng)build僧须。
這時(shí)候打開http://localhost:1841/ 會(huì)看到Cmd自動(dòng)創(chuàng)建的默認(rèn)首頁長(zhǎng)這樣子。6.x版新增加的Triton主題和以前的主題有明顯的不同项炼。
打開D:\TutorialApp目錄担平,看下Cmd自動(dòng)創(chuàng)建的目錄和文件:
.sencha/ # 里面存放的大多都是配置相關(guān)的文件,一般不需要修改
ext/ # Ext JS SDK的一份copy锭部,所以才會(huì)這么大
index.html # 首頁
app.json # 項(xiàng)目主配置文件
app.js # 項(xiàng)目主程序
app/ # 項(xiàng)目源碼目錄
model/ # Model目錄
store/ # Store目錄
view/ # View目錄
main/ # 首頁的目錄
Main.js # 首頁的View
MainModel.js # 首頁的ViewModel
MainController.js # 首頁的ViewController
Application.js # Ext.Application
packages/ # Sencha Cmd packages
workspace.json # Workspace的描述文件
build/ # 保存項(xiàng)目最終的build結(jié)果
還有一些目錄和文件沒有列舉出來暂论,那些目錄和文件一般都不需要我們?nèi)バ薷模捌诳梢院雎浴?br>
對(duì)我們來說空免,最重要的目錄就是app目錄空另,這是項(xiàng)目的源碼目錄,我們寫的代碼都保存在里面蹋砚。
app目錄下包含三個(gè)子目錄:
- model: 保存Model對(duì)象扼菠,Cmd也提供了命令來創(chuàng)建Ext JS中的Model對(duì)象摄杂。比如User,它包含id循榆,name析恢,email三個(gè)字段。在命令行中運(yùn)行:
cd D:\TutorialApp
sencha generate model user.User id:int,name,email
運(yùn)行Cmd的命令需要先進(jìn)入項(xiàng)目目錄秧饮,運(yùn)行之后會(huì)看到model目錄里多了一個(gè)子目錄user映挂,user目錄里有新建的User.js文件。
app/ # 項(xiàng)目源碼目錄
model/ # Model目錄
user/ # user子目錄
User.js # User.js定義了User的字段
關(guān)于Ext JS的Model的具體用法盗尸,請(qǐng)參照官方API文檔:Ext.data.Model
- store: Ext JS的Store可以理解為Model對(duì)應(yīng)的數(shù)據(jù)集合柑船,在Store中可以定義怎么去讀取Model。具體用法泼各,請(qǐng)參照官方API文檔:Ext.data.Store
- view:所有和UI相關(guān)的代碼都保存在這里鞍时,比如窗口,表格扣蜻,圖表等逆巍。可以為每個(gè)UI創(chuàng)建對(duì)應(yīng)的ViewController(Ext.app.ViewController)和ViewModel(Ext.app.ViewModel)莽使。
由于這個(gè)示例程序要演示的是創(chuàng)建一個(gè)登錄窗口锐极,只有等登錄完成之后才會(huì)顯示首頁。所以首先要打開項(xiàng)目根目錄下的app.js芳肌,將和TutorialApp.view.main.Main相關(guān)的代碼刪除灵再。修改后的app.js長(zhǎng)這樣:
Ext.application({
name: 'TutorialApp',
extend: 'TutorialApp.Application
});
如果你仍然保持sencha app watch的運(yùn)行狀態(tài),則Cmd會(huì)檢測(cè)到你對(duì)app.js的修改庇勃。此時(shí)訪問首頁檬嘀,就會(huì)看到一片空白槽驶。
接著來創(chuàng)建用戶的登錄窗口责嚷,它是長(zhǎng)這樣子的:
可以在app\view目錄里手動(dòng)創(chuàng)建login子目錄,并在login目錄下手動(dòng)創(chuàng)建Login.js和LoginController.js掂铐。也可以在命令行中運(yùn)行以下命令來讓Cmd自動(dòng)創(chuàng)建:
cd D:\TutorialApp
sencha generate view -base Ext.window.Window login.Login
-base參數(shù)用來設(shè)置創(chuàng)建的UI是哪種類型罕拂,由于我們要?jiǎng)?chuàng)建的是窗口,所以繼承的是Ext.window.Window全陨。
Login.js是登錄窗口的代碼爆班,最后長(zhǎng)這樣:
Ext.define('TutorialApp.view.login.Login', {
extend: 'Ext.window.Window',
xtype: 'login',
//Login窗口會(huì)包含一個(gè)表單(Ext.form.Panel)
//LoginController里定義了Login窗口會(huì)使用到的方法onLoginClick
//requires可以確保這2個(gè)類會(huì)在Login初始化完成之前先被初始化
requires: [
'TutorialApp.view.login.LoginController',
'Ext.form.Panel'
],
//綁定controller,綁定時(shí)使用的是別名
controller: 'login',
//padding: 10px
bodyPadding: 10,
//窗口的標(biāo)題欄文字
title: 'Login Window',
//隱藏窗口右上角的關(guān)閉按鈕"x"
closable: false,
//Window的autoShow默認(rèn)為false
//Window可以用show()和hide()來手動(dòng)顯示和隱藏
//把a(bǔ)utoShow設(shè)為true, 則在Window創(chuàng)建之后會(huì)自動(dòng)顯示
autoShow: true,
//把窗口里的UI組件放在items里
items: {
//表單
xtype: 'form',
reference: 'form',
//把表單里的UI組件放在表單的items里
items: [{
//供用戶輸入用戶名的文本框
xtype: 'textfield',
name: 'username',
//fieldLabel是顯示在文本框前的標(biāo)簽文字
fieldLabel: 'Username',
//打開非空校驗(yàn)辱姨,即要求輸入的用戶名不能為空
allowBlank: false
}, {
//供用戶輸入密碼的文本框
xtype: 'textfield',
name: 'password',
//inputType設(shè)為password柿菩,則用戶輸入的內(nèi)容會(huì)以*回顯在屏幕上
inputType: 'password',
fieldLabel: 'Password',
allowBlank: false
}, {
//顯示在密碼輸入框下方的文字
xtype: 'displayfield',
hideEmptyLabel: false,
value: 'Enter any non-blank password'
}],
//表單的按鈕
buttons: [{
//按鈕上的顯示文字
text: 'Login',
//設(shè)為true,則Login按鈕在表單通過校驗(yàn)前是不能被點(diǎn)擊的
formBind: true,
listeners: {
//當(dāng)按鈕被點(diǎn)擊時(shí)
click: 'onLoginClick'
}
}]
}
});
LoginController.js是Login的Controller雨涛,最后長(zhǎng)這樣:
Ext.define('TutorialApp.view.login.LoginController', {
extend: 'Ext.app.ViewController',
//定義別名為login
alias: 'controller.login',
//當(dāng)Login按鈕被點(diǎn)擊時(shí)
onLoginClick: function() {
//這本例中使用localStorage來保存用戶的登錄狀態(tài)
//這里省略了用戶信息的遠(yuǎn)程校驗(yàn)過程
//只要用戶輸入用戶名和密碼枢舶,點(diǎn)擊Login按鈕即認(rèn)為用戶成功登陸
localStorage.setItem("TutorialLoggedIn", true);
//getView()返回的是controller綁定的view, 在本例中就是Login窗口
//登錄后不再需要Login窗口懦胞,所以調(diào)用destroy()來刪除
this.getView().destroy();
//關(guān)閉Login窗口后,需要顯示首頁
//使用Ext.create()來創(chuàng)建view\main\Main.js
Ext.create({
xtype: 'app-main'
});
}
});
登錄窗口寫好了凉泄,但還不會(huì)顯示躏尉,需要修改app\Application.js。
Application.js最后長(zhǎng)這樣:
Ext.define('TutorialApp.Application', {
extend: 'Ext.app.Application',
name: 'TutorialApp',
stores: [
// TODO: add global / shared stores here
],
views: [
'TutorialApp.view.login.Login',
'TutorialApp.view.main.Main'
],
launch: function () {
var loggedIn;
//從localStorage讀取用戶登錄狀態(tài)
loggedIn = localStorage.getItem("TutorialLoggedIn");
//如果用戶已登錄后众,則顯示首頁胀糜,否則顯示Login窗口
Ext.create({
xtype: loggedIn ? 'app-main' : 'login'
});
},
onAppUpdate: function () {
Ext.Msg.confirm('Application Update', 'This application has an update, reload?',
function (choice) {
if (choice === 'yes') {
window.location.reload();
}
}
);
}
});
最后在首頁上加上一個(gè)Logout按鈕,修改后的app\main\Main.js長(zhǎng)這樣:
Ext.define('TutorialApp.view.main.Main', {
extend: 'Ext.tab.Panel',
xtype: 'app-main',
requires: [
'Ext.plugin.Viewport',
'Ext.window.MessageBox',
'TutorialApp.view.main.MainController',
'TutorialApp.view.main.MainModel',
'TutorialApp.view.main.List'
],
controller: 'main',
viewModel: 'main',
plugins: 'viewport',
ui: 'navigation',
tabBarHeaderPosition: 1,
titleRotation: 0,
tabRotation: 0,
header: {
layout: {
align: 'stretchmax'
},
title: {
bind: {
text: '{name}'
},
flex: 0
},
iconCls: 'fa-th-list',
//添加Logout按鈕
items: [{
xtype: 'button',
text: 'Logout',
margin: '10 0',
handler: 'onClickButton'
}]
},
tabBar: {
flex: 1,
layout: {
align: 'stretch',
overflowHandler: 'none'
}
},
responsiveConfig: {
tall: {
headerPosition: 'top'
},
wide: {
headerPosition: 'left'
}
},
defaults: {
bodyPadding: 20,
tabConfig: {
plugins: 'responsive',
responsiveConfig: {
wide: {
iconAlign: 'left',
textAlign: 'left'
},
tall: {
iconAlign: 'top',
textAlign: 'center',
width: 120
}
}
}
},
items: [{
title: 'Home',
iconCls: 'fa-home',
items: [{
xtype: 'mainlist'
}]
}, {
title: 'Users',
iconCls: 'fa-user',
bind: {
html: '{loremIpsum}'
}
}, {
title: 'Groups',
iconCls: 'fa-users',
bind: {
html: '{loremIpsum}'
}
}, {
title: 'Settings',
iconCls: 'fa-cog',
bind: {
html: '{loremIpsum}'
}
}]
});
在首頁的對(duì)應(yīng)的Controller蒂誉,app\main\MainController.js中添加Logout對(duì)應(yīng)的click方法
Ext.define('TutorialApp.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
onItemSelected: function (sender, record) {
Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this);
},
onConfirm: function (choice) {
if (choice === 'yes') {
//
}
},
//點(diǎn)擊Logout按鈕
onClickButton: function () {
//刪除保存在localStorage中的登錄狀態(tài)
localStorage.removeItem('TutorialLoggedIn');
//刪除首頁
this.getView().destroy();
//創(chuàng)建Login窗口
Ext.create({
xtype: 'login'
});
}
});
寫代碼到此就完成了教藻,運(yùn)行sencha app build命令
cd D:\TutorialApp
sencha app build
運(yùn)行結(jié)束后,在build目錄下會(huì)生成production子目錄右锨,可以把該目錄下的TutorialApp目錄發(fā)布到其他服務(wù)器上怖竭,比如Apache HTTP Server的htdocs目錄里。