天天看點

ASP.NET MVC4 中整合 NHibernate3.3、Spring.NET2.0、ExtJS4 筆記五:ExtJS4.0整合

本文源碼位址:http://download.csdn.net/detail/xz2001/4944407

一、介紹與下載下傳

整個架構的整合中,ExtJS比較簡單,與NHibernate、Spring.NET幾乎沒有什麼關系,唯一需要的是JSON或XML格式資料。

在寫這篇檔案時,ExtJS的最新版是4.0.7,本文也就采用這個版本。

ExtJS4.0與2、3有明顯的差別,3.x向4.x的更新,不是2.x向3.x更新那樣簡單,4.x中整體性能有明顯提升。另外,4.x中使用了流行的MVC模式,還有懶加載的機制等等。

ExtJS官方下載下傳位址:http://www.sencha.com/products/extjs/download/

二、安裝部署

為了清晰項目結構,個人喜歡把所有js、css、img以及第三方用戶端架構都放在Web項目的Content目錄中。其中的css、主題暫時不需要,可以先清空,然後把extjs解壓後的目錄整個複制進來。如下圖:

ASP.NET MVC4 中整合 NHibernate3.3、Spring.NET2.0、ExtJS4 筆記五:ExtJS4.0整合

這裡說一下,由于extjs架構中的檔案太多,複制進來的時候特别慢,我的電腦等了估計有5分鐘左右。是以,可以把extjs精簡一下,比如doc、examples等目錄删除,另外,也可以在VS解決方案資料總管中排除extjs整個目錄,這樣以後會快很多。

三、項目結構

既然使用了ExtJS4.o,肯定要用4.0中的MVC開發模式。在編寫之前,先看下我的目錄結構:

ASP.NET MVC4 中整合 NHibernate3.3、Spring.NET2.0、ExtJS4 筆記五:ExtJS4.0整合

有過MVC開發經驗的應該一眼明白。事實上,MVC更多的是一種約定,比如:視圖放在子產品名稱的目錄下,系統會自動來這個目錄下搜尋。至于能不能放到别處,本人沒仔細研究,不過,ASP.NET MVC中的視圖是可以的,隻要重寫“WebFormViewEngine”類,詳細看這裡:http://blog.csdn.net/xz2001/article/details/7031756

另外,看一下Area的結構:

ASP.NET MVC4 中整合 NHibernate3.3、Spring.NET2.0、ExtJS4 筆記五:ExtJS4.0整合

這裡大概說幾點:

1、ExtJS4.0中所有的資源檔案是動态加載的,具體可以了解"Ext Loader"加載機制;

2、ExtJS4.0項目是以子產品為機關進行開發,在ExtJS中是以命名空間展現的;

3、每個子產品的入口檔案是app.js,app中要聲明需要使用的控制器;

4、控制器中要聲明使用到的View、Model以及Store。理論上說,應該把所有事件的處理放在Controller中,就如在Struts、ASP.NET MVC中開發一樣,事件應該由控制器捕獲和處理,View僅僅負責渲染控件、顯示資料;

5、Model與Struts、ASP.NET MVC中的實體類差不多,但不同于領域模型中的領域對象,這裡的Model僅僅含有資料,不含有任何方法;

6、Store在ExtJS中扮演着資料源與Model之間的橋梁,通過與Proxy對象進行資料的CURD操作;

7、4.0中的視圖負責控件的渲染,實事上視圖中的代碼功能與之前的版本很相似。

四、編寫代碼

由于用到的js檔案較多,這裡我就直接上代碼了,不清楚的對應上面的截圖看一下。

1、app.js

Ext.application({
    name: 'AM',


    appFolder: '/Content/Manage/app',
    controllers: [
	    'Menu',
	    'User'
	],

	autoCreateViewport: true
});
           

注:這裡使用了2個Controller,需要在這裡注冊下,并自動建立Viewport元件,會自動從"appFolder"參數指定的目錄中搜尋。

2、app/Viewport.js

Ext.define('AM.view.Viewport', {
    extend: 'Ext.container.Viewport',

    requires: [
        'AM.view.Head',
        'AM.view.Menu',
        'AM.view.Foot',
        'AM.view.Body'
    ],

    layout: 'border',

    items: [{
        region: 'north',
        height: 45,
        xtype: 'head'
    },{
        region: 'west',
        width: 225,
        xtype: 'menu'
    },{
        region: 'south',
        height: 25,
        xtype: 'foot'
    },{
        region: 'center',
        xtype: 'body'
    }]
});
           

注:requires聲明必須先引入的類,其共有四個子元素,分别布局在上、下、左和中間,下面一個一個看。

3、app/Menu.js

該控件布局在左側,是項目的管理菜單。

Ext.define('AM.view.Menu', {
	extend : 'Ext.panel.Panel',
	alias : 'widget.menu',
	requires : [ 'AM.view.menu.Tree' ],
	margins : '0 0 0 5',
	split : true,
	collapsible : true,
	header : true,
	title : '管理菜單',
	initComponent : function() {
		this.items = [{ xtype: 'menuTree' }];
		this.callParent(arguments);
	}
});
           

注:AM.view.Menu中添加了一個子元素,其xtype是“menuTree”,實際上是一個Tree對象。稍後會有這個對象。

4、app/Head.js

布局在上方,一般用來顯示項目名稱和一些快捷導航,這裡為了友善沒有顯示這麼複雜,就顯示“加載中...”

Ext.define('AM.view.Head', {
	extend : 'Ext.panel.Panel',
	alias : 'widget.head',
	margins : '5 5 0 5',
	split : true,
	header : false,
	collapsible : true,
	initComponent : function() {
		this.html = "<div>加載中...</div>";
		this.callParent(arguments);
	}
});
           

5、app/Foot.js

顯示在最下方,一般可以用來顯示目前登入的管理者資訊,這裡為了友善,也沒有顯示。

Ext.define('AM.view.Foot', {
	extend : 'Ext.panel.Panel',
	alias : 'widget.foot',
	margins : '5 5 5 5',
	header : false,
	frame : true,
	collapsible : true,
	initComponent : function() {
		this.callParent(arguments);
	}
});
           

6.app/Body.js

管理子產品的主體部分,根據管理的子產品不同,即時渲染相應的控件來顯示資料、修改資料、添加、删除資料等操作。這裡隻是加載了一個xtype為'userList',顯示的是使用者清單,後面會說到這個控件。

Ext.define('AM.view.Body', {
	extend : 'Ext.panel.Panel',
	alias : 'widget.body',
	requires : [ 'AM.view.user.List' ],
	margins : '0 5 0 0',
	border : 0,
	header : false,
	baseCls : 'x-plain',
	collapsible : true,
	initComponent : function() {
		this.items = [ {
		    xtype: 'userList'
		} ];
		this.callParent(arguments);
	}
});
           

7、app/controller/Menu.js

這個是左側菜單的控制器,處理左側菜單的事件以及事件的處理,這裡隻是在單擊菜單時寫入了一條日志。

Ext.define('AM.controller.Menu', {
    extend: 'Ext.app.Controller',
    stores: ['Menu'],
    views: ['menu.Tree'],
    init: function() {
		this.control({
	        'menuTree': {
	            itemclick: this.selectItem
	        }
	    });
    },
    selectItem: function(){
    	console.log('click item');
    }
});
           

8、app/store/Menu.js

左側菜單的Store對象,負責處理資料。

Ext.define('AM.store.Menu', {
	extend: 'Ext.data.TreeStore',
	autoLoad : true,
    proxy: {
        type: 'ajax',
        api: {
		    read: '/Content/Manage/data/menus.js'
		},
		reader: {
            type: 'json',
            root: 'childrens'
        }
    },
    sorters: [{
        property: 'leaf',
        direction: 'ASC'
    }],
    root: {
        nodeType: 'async',
        text: 'Ext JS',
        expanded: true
    }
});
           

這裡調用的是靜态資料,頁面URL是"/Content/Manage/data/menus.js",其資料如下:

{childrens:[
{id:'01',text:'資料管理',childrens:[
{id:'01-01',text:'新聞管理',leaf:true},
{id:'01-02',text:'分類管理',leaf:true},
{id:'01-03',text:'公告管理',leaf:true}
]},
{id:'02',text:'系統配置',leaf:true}
]}
           

9、app/view/menu/Tree.js

左側菜單的視圖檔案,負責渲染元件:

Ext.define('AM.view.menu.Tree' ,{
    extend: 'Ext.tree.Panel',
    alias : 'widget.menuTree',
    header : false,
    border : 0,
    store: 'Menu',
    rootVisible: false
});
           

現在來看使用者的相關對象,先看控制器:

10、app/controller/User.js

Ext.define('AM.controller.User', {
    extend: 'Ext.app.Controller',
    stores: ['User'],
    views: ['user.List'],
    models: ['User']
});
           

由于使用者資料需要Model對象,來看下:

11、app/model/User.js

Ext.define('AM.model.User', {
	extend : 'Ext.data.Model',
	fields : [ 'name', 'email' ]
});
           

再看下Store:

12、app/store/User.js

Ext.define('AM.store.User', {
    extend: 'Ext.data.Store',
    model: 'AM.model.User',
    autoLoad: true,
    sorters: [{
        property: 'code',
        direction: 'ASC'
      }],
    proxy: {
        type: 'ajax',
        api: {
            read: '/Content/Manage/data/userList.js'
        },
        reader: {
            type: 'json',
            root: 'users',
            successProperty: 'success'
        }
    },
    listeners:{
    	update: function(store, record){
    		console.log('listeners update. name='+record.get('name'));
    	}
    }
});
           

這個Store稍微複雜些,使用了Proxy對象,複雜與背景進行資料互動。這裡不詳解,以後的文章都會一一細說。

這裡隻說/Content/Manage/data/userList.js傳回的資料:

{
    success: true,
    users: [
        {id: 1, name: '崔北為',    email: '[email protected]'},
        {id: 2, name: '李軍', email: '[email protected]'},
        {id: 3, name: '錢雲祿', email: '[email protected]'}
    ]
}
           

13、app/view/user/List.js

Ext.define('AM.view.user.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.userList',
    title : 'All Users',
    store: 'User',
    columns: [
        {header: 'Name',  dataIndex: 'name',  flex: 1},
        {header: 'Email', dataIndex: 'email', flex: 1}
    ],
    buttons:[
        {text:'add',action:'add'},
        {text:'delete',action:'delete'}
    ]        
});
           

到此,所有的js檔案全部搞定,可以測試運作了。

五、運作預覽

ASP.NET MVC4 中整合 NHibernate3.3、Spring.NET2.0、ExtJS4 筆記五:ExtJS4.0整合