用ExtJs做前端框架,一般而言,主框架基本都會使用Border布局。
大概布局就像這個樣子。
頂部左側一般顯示系統名稱,右側用戶姓名。
左側是一個手風琴(Accordion),或者其他的,比如Tree,用以實現導航或功能菜單。
中間就是主內容了,Tab選項卡的形式,以輕松支持多功能,同時可輕松切換,若是整個界面只支持最多一個頁面的話,對於一個后台系統來說,確實不太方便。
當然,也可以多加幾個模塊,如頂部加一個用戶信息及常用操作的工具條。
=========================分隔線====================================
如果只是簡單的實現這樣的布局,那么代碼可以很簡單。
var vp = Ext.create('Ext.Viewport', { layout: 'border', items: [ { xtype: 'panel', region: 'north', height: 60 }, { xtype: 'panel', region: 'west', width: 200 }, { xtype:'panel', region:'center' } ] });
定義布局為border,再定義三個內容塊,分別為頂部,左側和中間。
在實際項目中,直接這么簡單的定義各塊內容行嗎?行,沒問題,肯定能跑起來。
但對於后期代碼閱讀、維護、擴展等,那問題就來了。
為什么?因為各模塊的內容遠不只這么簡單,比如左側模塊,簡單一些,可能就是一個Tree空間,甚至更簡單一些,只是幾個固定的項,那么,負責一些呢。
以此系統來說,左側包含三塊內容:欄目列表、功能菜單、系統設置,這三塊內容內部各包含一個Tree。
如果代碼全部寫在內容的Items里的話,層層嵌套,最終會導致單個文件過於龐大,難於閱讀及維護。
=========================分隔線====================================
所以,還是建議以ExtJs官方推薦的方式編寫腳本,就是以定義(Ext.Define)的方式實現各模塊,再通過動態加載按需加載所需要的文件。
且按功能分類的將腳本寫在不同的文件中,可以看下此系統的所有js文件:
Common:存放在些比較通用的東西,比如數據的Model,一些工具方法等;
Function:對應左側模塊的功能菜單,所有功能菜單里的功能都放在這;
Main:主框架文件夾,圖片上有幾個是沒用的,暫時還沒刪。Center是中間主內容,LeftPanel是左側模塊,LeftTree是欄目樹,SysSetTree是功能菜單樹及洗頭系統設置樹。
Show:前端流量數據展示的一些功能;
Sys:系統設置相關功能文件。
=========================分隔線====================================
好了,說說主框架的搭建吧。
Ext.define("Yiqi.Main.Main", { extend: 'Ext.container.Viewport', requires: ['Yiqi.Main.Center', 'Yiqi.Main.LeftPanel', 'Yiqi.Common.Tools'], initComponent: function () { this.buildTop(); this.buildLeft(); this.buildCenter(); Ext.apply(this, { layout: 'border', items: [ this.topPart, this.leftPart, this.centerPart ] }); this.callParent(arguments); }, buildTop: function () { // 頭部 this.topPart = Ext.create('Ext.panel.Panel', { region: 'north', margin: '5 5 0 5', header: false, split: true, collapsible: true, collapseMode: 'mini', hideCollapseTool: true, contentEl: 'top_box', height: 45 }); }, buildLeft: function () { //左側菜單 this.leftPart = Ext.create('Yiqi.Main.LeftPanel', { region: 'west', //flex:1, title: '功能菜單' }); }, buildCenter: function () { //主體內容 this.centerPart = Ext.create('Yiqi.Main.Center', { region: 'center' //flex:4 }); } });
Ext.define的方式,定義整個主框架。內部各模塊組件化,這樣代碼看上去,簡潔多了。
=========================分隔線====================================
因為我需要自定義功能菜單是以Tab選項卡的形式打開還是彈出window的形式打開,所以,整個主框架,也就這一塊花了點心思。
先看下功能菜單是怎么樣的。
功能地址,就是功能所在的文件路徑&文件名,也是模塊的類名。
了解ExtJs動態加載的應該知道這個。
比如:用戶管理,它的功能地址是Yiqi.Sys.Security.UserList,Yiqi是定義的動態加載根路徑,
所以,這塊功能的JS文件路徑實際是:\Sys\Security\UserList.js。
功能類的定義:
Ext.define('Yiqi.Sys.Security.UserList',{ extend:'xxxxxx', //.............TODO });
這也是使用ExtJs的一大好處,功能菜單,可以隨意的定義功能地址、打開方式等等,而不需要改任何代碼,當然,你得先把功能做好。
而打開方式的實現過程,也比較簡單,定義樹中node的單擊事件,判斷單擊的node,有無定義功能地址,如果有,再判斷打開方式,如果是彈出窗,則以window的形式打開;如果是選項卡,則以選項卡的方式打開。
onItemClick: function (view, rec, item, idx, e) { var path = rec.get("LoadPath"); //--功能地址 var openType = rec.get("OpenType"); //--打開方式 var me = this; if (!Ext.Object.isEmpty(path) && !Ext.Object.isEmpty(openType)) {if (openType == "window") { var win_id = 'syswin_' + rec.get("id"); var win = Ext.WindowManager.get(win_id); if (win) { Ext.WindowManager.bringToFront(win); } else { win = Ext.create(path, { title: rec.get("text"), iconCls: rec.get("iconCls"), id: win_id }); win.show(); } } else if (openType == "tab") { //--選項卡方式打開,先判斷當前功能是否已經打開,如果已打開,則無需新建,直接將該功能設為活動選項卡就行了。 //--me.ownerCt.ownerCt.centerPart是主框架的中間內容模塊。 var tab = me.ownerCt.ownerCt.centerPart.getComponent('tab_sys_' + rec.get('id')); if (!tab) { var newitem = Ext.create(path, {}); tab = Ext.create('Ext.panel.Panel', { title: rec.get('text'), itemId: 'tab_sys_' + rec.get('id'), layout: 'fit', closable: true, iconCls: rec.get('iconCls') || 'icon_preview', items: newitem }); me.ownerCt.ownerCt.centerPart.add(tab); } //--設為活動選項卡 me.ownerCt.ownerCt.centerPart.setActiveTab(tab); } } }
至此,主框架就差不多了~~~