在EXT的SDK中包含有一篇文章寫的很好,可以作為廣大初學EXT的ITer們的必讀文章,因為全文都是英文,讀起來非常不方便,所以在這里將該篇文章用本人的語言壓縮成以下的博文:(僅供參考)
原文地址請參考:https://github.com/sndpl/extjs4_mvc_skel 由4樓二胖提供,或者可以直接到ext官網下載SDK.
在MVC的布局模式中,所有的類都放置在app文件夾中,這個文件夾還包含了一些子文件夾用於命名你的models,views,controllers,stores.下圖為simple這個應用程序的文件夾結構:
在ext-4.0文件夾中應包含必須文件:ext-debug.js和ext.js;
而我們的index.html中應include這兩個文件,在index.html中,僅需要一下的代碼:

1 <html>
2 <head>
3 <title>Account Manager</title>
4
5 <link rel="stylesheet" type="text/css" href="ext-4.0/resources/css/ext-all.css">
6
7 <script type="text/javascript" src="ext-4.0/ext-debug.js"></script>
8
9 <script type="text/javascript" src="app.js"></script>
10 </head>
11 <body></body>
12 </html>
每一個ext js應用程序都由一個Application類作為開始,這個Application包含了全局設置,比如應用程序的名稱,以及需要引用到的所有的models,views,controllers.這個Application同時也包含一個launch啟動方法,這個方法會在所有的東西都准備好了以后自動運行。
在app.js中創建我們的應用程序
下面我們來創建一個簡單的賬戶管理程序,這個程序會幫助我們管理我們的賬戶,首先我們需要一個全局的命名空間,我們的應用程序里面所用到所有類都會在這個命名空間里面。通常我們會選擇一個簡短的名字作為全局的命名空間:比如AM,來看一下我們的app.js中的代碼:

1 Ext.application({
2 name: 'AM',
3
4 appFolder: 'app',
5
6 launch: function() {
7 Ext.create('Ext.container.Viewport', {
8 layout: 'fit',
9 items: [
10 {
11 xtype: 'panel',
12 title: 'Users',
13 html : 'List of users will go here'
14 }
15 ]
16 });
17 }
18 });
首先,我們調用Ext.application去創建一個Application類,傳遞一個名字叫AM。這樣它就能夠自動的為我們創建一個全局的變量AM給我們,並將這個命名空間注冊到Ext.Loader.代碼中還創建了一個launch函數,這個函數里面創建了一個Viewport,它包含一個將會充滿屏幕的panel.此時的效果如下圖所示:
定義一個控制器
控制器是跟應用程序綁定在一起的,控制器所做的工作就是監聽事件並作出相應,監聽的事件通常是在views中,下面我們來創建一個控制器,在app/controller/下面新建一個User.js 里面代碼如下:

1 Ext.define('AM.controller.Users', {
2 extend: 'Ext.app.Controller',
3
4 init: function() {
5 console.log('Initialized Users! This happens before the Application launch function is called');
6 }
7 });
因為我們創建了這個控制器,應用程序要與它關聯的話就需要添加如下的代碼:app.js改變如下:

1 Ext.application({
2 ...
3
4 controllers: [
5 'Users'
6 ],
7
8 ...
9 });
當我們的 應用程序加載進來的時候,這個Users控制器就會自動的加載進來,(因為我們把它聲明在了application的定義上面),這個控制器的init方法會在應用程序的launch方法執行之間調用。在init方法里面就是我們的控制器如何與view進行交互的一些邏輯,具體看代碼:

1 Ext.define('AM.controller.Users', {
2 extend: 'Ext.app.Controller',
3
4 init: function() {
5 this.control({
6 'viewport > panel': { //這里是css選擇器的形式
7 render: this.onPanelRendered //當頁面進行渲染的時候就會促發該應用程序的onPanelRendered方法。
8 }
9 });
10 },
11
12 onPanelRendered: function() {
13 console.log('The panel was rendered');
14 }
15 });
我們重新刷新頁面,可以看到如下效果:
定義一個視圖
現在我們些的代碼就只有兩個js文件,app.js和User.js。接下來我們要繼續組織一下我們的應用程序,開始用到views.
View無非就是一個組件,通常會定義為一個Ext js component的子類。下面我們要創建一個用戶列表,可以新建一個List.js,位於app/view/user/下。List.js代碼如下:

1 Ext.define('AM.view.user.List' ,{
2 extend: 'Ext.grid.Panel',
3 alias : 'widget.userlist', //別名為userlist
4
5 title : 'All Users',
6
7 initComponent: function() { //初始化組件函數
8 this.store = {
9 fields: ['name', 'email'],
10 data : [
11 {name: 'Ed', email: 'ed@sencha.com'},
12 {name: 'Tommy', email: 'tommy@sencha.com'}
13 ]
14 };
15
16 this.columns = [
17 {header: 'Name', dataIndex: 'name', flex: 1},
18 {header: 'Email', dataIndex: 'email', flex: 1}
19 ];
20
21 this.callParent(arguments);
22 }
23 });
olumns(可以渲染的列)。接下來我們需要將這個view添加到我們的控制器中,因為我們使用了特殊的‘widget.'格式創建了一個這個視圖的一個別名,所以我們可以使用userlist作為xtype,可以像通常使用Panel的形式一樣來使用這個view.所以控制器的代碼改變如下:

1 Ext.define('AM.controller.Users', {
2 extend: 'Ext.app.Controller',
3
4 views: [
5 'user.List'
6 ],
7
8 init: ...
9
10 onPanelRendered: ...
11 });
在app.js中,launch方法內的代碼就可以改變為如下了:(view替代原來的內容)

1 Ext.application({
2 ...
3
4 launch: function() {
5 Ext.create('Ext.container.Viewport', {
6 layout: 'fit',
7 items: {
8 xtype: 'userlist'
9 }
10 });
11 }
12 });
下面是代碼修改后的頁面顯示效果:
控制表格
注意到我們的onPanelRendered方法仍在調用,這是因為我們的表格仍然符合’viewport>panel‘選擇器。其原因是我們的類繼承了grid,歸根結底是繼承了Panel。
接下來我們再個表格添加雙擊的監聽事件,以便於稍后的表格編輯。代碼如下:

1 Ext.define('AM.controller.Users', {
2 extend: 'Ext.app.Controller',
3
4 views: [
5 'user.List'
6 ],
7
8 init: function() {
9 this.control({
10 'userlist': {
11 itemdblclick: this.editUser
12 }
13 });
14 },
15
16 editUser: function(grid, record) {
17 console.log('Double clicked on ' + record.get('name'));
18 }
19 });
上面的代碼寫完后我們在表格中雙擊,控制台就會顯示出相應的信息。在控制台中顯示相應的信息自然很方便,不過我們現在要的是能夠編輯表格,所以我們需要添加一個新的view.在app/view/user/目錄下新建一個文件:Edit.js,里面代碼如下:

1 Ext.define('AM.view.user.Edit', { //注意定義名稱 的形式
2 extend: 'Ext.window.Window',
3 alias : 'widget.useredit',
4
5 title : 'Edit User',
6 layout: 'fit',
7 autoShow: true,
8
9 initComponent: function() {
10 this.items = [
11 {
12 xtype: 'form',
13 items: [
14 {
15 xtype: 'textfield',
16 name : 'name',
17 fieldLabel: 'Name'
18 },
19 {
20 xtype: 'textfield',
21 name : 'email',
22 fieldLabel: 'Email'
23 }
24 ]
25 }
26 ];
27
28 this.buttons = [
29 {
30 text: 'Save',
31 action: 'save'
32 },
33 {
34 text: 'Cancel',
35 scope: this,
36 handler: this.close
37 }
38 ];
39
40 this.callParent(arguments);
41 }
42 });
接下來就是如何將這個view關聯到我們的應用程序中。在控制器中找到原來的editUser方法,將方法改為如下代碼所示:

1 Ext.define('AM.controller.Users', {
2 extend: 'Ext.app.Controller',
3
4 views: [
5 'user.List',
6 'user.Edit' //添加該view
7 ],
8
9 init: ...
10
11 editUser: function(grid, record) {
12 var view = Ext.widget('useredit'); //創建該view
13
14 view.down('form').loadRecord(record); //數據載入
15 }
16 });
代碼中的down是EXT中的方法,能夠往下查詢到括號中對應的內容。保存代碼,刷新頁面,雙擊用戶列表,頁面顯示如下:
創建model和store
現在我們有了編輯的表格,差不多可以開始對表格進行操作了,但在此之前我們還需要對代碼進行一下重構。
在我們的AM.view.user.List這個view中,我們創建了一個store混合在代碼中,這種方式也能讓我們的應用程序工作的很好,但我們希望將它放在其他地方以便於在數據更新時得到方便.在這里我們主要把view中的代碼拆開將store保存於另一個文件中,文件目錄為:app/store/User.js;其代碼具體為:

1 Ext.define('AM.store.Users', {
2 extend: 'Ext.data.Store',
3 fields: ['name', 'email'],
4 data: [
5 {name: 'Ed', email: 'ed@sencha.com'},
6 {name: 'Tommy', email: 'tommy@sencha.com'}
7 ]
8 });
我們需要做兩個小的改動,一是在控制器中添加store的引用

1 Ext.define('AM.controller.Users', {
2 extend: 'Ext.app.Controller',
3 stores: [
4 'Users'
5 ],
6 ...
7 });
另一個改動是將去掉了store的view重新添加對他的引用

1 Ext.define('AM.view.user.List' ,{
2 extend: 'Ext.grid.Panel',
3 alias : 'widget.userlist',
4
5 //we no longer define the Users store in the `initComponent` method
6 store: 'Users',
7
8 ...
9 });
在上面的修改中,store里面還包含了fields字段,在EXT中,我們仍然可以將它分離出來,放在model中。新建User.js位於目錄app/model/下。代碼如下:

1 Ext.define('AM.model.User', {
2 extend: 'Ext.data.Model',
3 fields: ['name', 'email']
4 });
接下來我們就要更新一下我們的store便於與model的關聯,同時也需要controller獲取一個model的關聯:

1 //the Users controller will make sure that the User model is included on the page and available to our app
2 Ext.define('AM.controller.Users', {
3 extend: 'Ext.app.Controller',
4 stores: ['Users'],
5 models: ['User'],
6 ...
7 });
8
9 // we now reference the Model instead of defining fields inline
10 Ext.define('AM.store.Users', {
11 extend: 'Ext.data.Store',
12 model: 'AM.model.User',
13
14 data: [
15 {name: 'Ed', email: 'ed@sencha.com'},
16 {name: 'Tommy', email: 'tommy@sencha.com'}
17 ]
18 });
我們的代碼重構會讓我們在下一步更輕松,若我們重新刷新頁面,並雙擊表格,頁面仍能按照我們的語氣彈出相應的窗口,現在是時候來完成表格的編輯方法了。
用模塊保存數據
現在我們有了用戶表格來加載數據,並在我們雙擊某一行的時候打開一個編輯窗口,我們可能會想保存經過修改的數據。首先我們來更新一下控制器的init方法里面的sava按鈕單擊事件。

1 Ext.define('AM.controller.Users', {
2 init: function() {
3 this.control({
4 'viewport > userlist': {
5 itemdblclick: this.editUser
6 },
7 'useredit button[action=save]': {
8 click: this.updateUser
9 }
10 });
11 },
12
13 updateUser: function(button) {
14 console.log('clicked the Save button');
15 }
16 });
刷新頁面,雙擊某行打開新窗口后,單擊保存按鈕后,控制台顯示相應信息,說明代碼正確執行了:
接下來我們再補充完整單擊保存按鈕的方法:

1 updateUser: function(button) {
2 var win = button.up('window'),
3 form = win.down('form'),
4 record = form.getRecord(),
5 values = form.getValues();
6
7 record.set(values);
8 win.close();
9 }
完成以上代碼后,在單擊保存按鈕,頁面的數據將會根據你的修改而顯示出你修改的數據。
保存到服務器
整個應用程序很簡單,接下來讓我們將這個應用程序與服務器端進行一下交互。在store中把數據全部錄在里面是一件很不爽的事情,因此我們可以將數據通過ajas讀取出來。
store修改如下:

1 Ext.define('AM.store.Users', {
2 extend: 'Ext.data.Store',
3 model: 'AM.model.User',
4 autoLoad: true,
5
6 proxy: {
7 type: 'ajax',
8 url: 'data/users.json',
9 reader: {
10 type: 'json',
11 root: 'users',
12 successProperty: 'success'
13 }
14 }
15 });
這里我們移除了data屬性,並用proxy替代。proxies是在EXT JS4中從store或model加載或保存數據的一種方法。在這里我們的程序會被告知從url為data/users.json的路徑中加載數據。
我們還添加了一個reader到代理上,這個reader能夠響應出一種數據格式以使store能夠讀懂。在這里的意思即是使用json閱讀器,並聲明root和successProperty屬性。最后我們創建一個json文件:data/users.json,並將之前的數據粘貼上去。

1 {
2 success: true,
3 users: [
4 {id: 1, name: 'Ed', email: 'ed@sencha.com'},
5 {id: 2, name: 'Tommy', email: 'tommy@sencha.com'}
6 ]
7 }
最后一件事我們要做的是發送動態修改信息到服務器。在這個例子中,我們使用靜態的JSON文件在服務器端,因此我們不會看到任何數據庫的改變但我們至少是可以知道整個應用程序是正常工作的。首先我們先對代理做出一點小小的改變,告訴他發送更新到一個不同的url上。

1 proxy: {
2 type: 'ajax',
3 api: {
4 read: 'data/users.json',
5 update: 'data/updateUsers.json'
6 },
7 reader: {
8 type: 'json',
9 root: 'users',
10 successProperty: 'success'
11 }
12 }
我們仍然從users.json中讀取數據,但任何更新都會發送到updateUsers.json上。這樣我們就能夠明確的知道所有的東西都在正常的工作中。這個updateUser.json文件包含{"success":true}.其他的改變我們要做的是告訴store在編輯完成后能夠同步。在這里僅僅需要在udateUser方法中添加一行代碼:

1 updateUser: function(button) {
2 var win = button.up('window'),
3 form = win.down('form'),
4 record = form.getRecord(),
5 values = form.getValues();
6
7 record.set(values);
8 win.close();
9 this.getUsersStore().sync();
10 }
接下來就測試了!!!!!!