摘要:根據(jù)模塊創(chuàng)建模塊失敗。在中,我們配置了標明了這是一個控制器模塊,點擊后會去觸發(fā)控制器加載動作。正常情況下同一個模塊的只加載一次。
前面幾篇文檔,我們基本實現(xiàn)了一個靜態(tài)的extjs頁面,本篇開始,實現(xiàn)左側(cè)導航樹與右側(cè)內(nèi)容的聯(lián)動,也就是點擊導航菜單,加載對應模塊頁面和業(yè)務邏輯,實現(xiàn)js文件的按需加載。業(yè)務需求是這樣的:
左側(cè)的treelist,當點擊某個節(jié)點的時候,系統(tǒng)根據(jù)tree數(shù)據(jù)里配置的模塊信息,加載這個模塊,并且把模塊對應的主頁面顯示在中間區(qū)域的tabpanel里。
改造主控制器:app/luter/controller/MainController.js監(jiān)聽導航樹的node點擊事件,進行后續(xù)處理:
"navlist": { "itemclick":function(el, record, opt){ //可以通過如下方式獲取點擊節(jié)點的數(shù)據(jù)。 var nodeData = record.node.data; } }
完整的代碼如下:
Ext.define("luter.controller.MainController", { extend: "Ext.app.Controller", views: ["main.ViewPort"], stores: ["NavTreeStore"], init: function (application) { var me = this; this.control({ "viewport": {//監(jiān)聽viewport的初始化事件,可以做點其他事情在這里,如有必要,記得viewport定義里的alias么? "beforerender": function () { console.log("viewport begin render at:" + new Date()); }, "afterrender": function () { console.log("viewport render finished at:" + new Date()); }, }, "syscontentpanel": { "afterrender": function (view) { console.log("syscontentpanel rendered at:" + new Date()); } }, "navlist": { "itemclick": function (el, record, opt) { var nodeData = record.node.data;//當前點擊節(jié)點的數(shù)據(jù) var tabpanel = Ext.getCmp("systabpanel");//中間tabpanel var tabcount = tabpanel.items.getCount();//當前tabpanel已經(jīng)打開幾個tab了。 var maxTabCount = 5;//最大打開的tab個數(shù) if (tabcount && tabcount > 5) { showFailMesg({ title: "為了更好的使用,最多允許打開5個頁面", msg: "您打開的頁面過多,請關(guān)掉一些!" }); return false; } if (nodeData.leaf) {//是打開新模塊,否則是展開樹節(jié)點 var moduleID = nodeData.module_id;//找到控制器ID,定義在tree的數(shù)據(jù)里modole_id if (!moduleID || moduleID == "") { showFailMesg({ title: "創(chuàng)建模塊失敗.", msg: "模塊加載錯誤,模塊id為空,創(chuàng)建模塊失敗" }); return false; } console.log("to add module with id:" + moduleID); //開始加載控制器 try { //嘗試加載這個控制器,這個過程就是按需ajax加載js文件的過程。 //如果這個模塊被加載過,則不會重復加載。 var module = luterapp.getController(moduleID); } catch (error) { showFailMesg({ msg: "根據(jù)模塊ID:" + moduleID + "創(chuàng)建模塊失敗。" + "左側(cè)菜單樹對應的測試數(shù)據(jù):app/testdata/menu.json
可能的原因 :
1、該模塊當前沒有實現(xiàn)." + "
2、模塊文件名稱與模塊名稱不一致,請檢查" + "Error: " + error + "" }); return false; } finally { } //判斷模塊是否加載下來,因為是ajax加載,所以還是判斷一下比較好 if (!module) { showFailMesg({ msg: "B:load module fail,the module object is null." + "
maybe :the module is Not available now." }); return false; } //加載到之后,默認去獲取控制器里views:[]數(shù)組里的第一個作為主視圖 var viewName = module.views[0]; console.log("will create a tab with view ,id:" + viewName); var view = module.getView(viewName); console.log("get the view el:" + view); if (!view) { showFailMesg({ msg: "Sorry ,to get the module view fail..." }); return false; } //判斷一下這個視圖是不是已經(jīng)加載到tabpanel里去了 var tabid = me.getTabId(moduleID); console.log("will create a tab with id:" + tabid); var notab = tabpanel.getComponent(tabid); var viewEL = view.create(); if (!viewEL) { showFailMesg({ msg: "Sorry ,to get the module viewEL fail..." }); return false; } if (!notab && null == notab) {//不存在新建 //不管是啥,都放到一個panel里面。 notab = tabpanel.add(Ext.create("Ext.panel.Panel", { tooltip: nodeData.text + ":" + nodeData.qtip, id: tabid, // tab的唯一id title: nodeData.text, // tab的標題 layout: "fit", // 填充布局,它不會讓load進來的東西改變大小 border: false, // 無邊框 closable: true, // 有關(guān)閉選項卡按鈕 iconCls: nodeData.iconCls, listeners: { // 偵聽tab頁被激活里觸發(fā)的動作 scope: this, destroy: function () { console.log("tab :" + tabid + ",has been destroyed") } }, items: [view.create()] })); //新建之后focus tabpanel.setActiveTab(notab); } else {//如果這個tab已經(jīng)存在了,則focus到這個tab tabpanel.setActiveTab(notab); } } else { //如果leaf =false,則說明這不是一個最底層節(jié)點,是目錄,展開。 console.log("tree node expand") } } } }); }, //這個方法從tab id里分離出控制器名稱 getTabId: function (mid) { var winid = mid; var c = winid.split("."); winid = c.pop(); return winid + "-tab"; } });
一般情況下,這個菜單數(shù)據(jù)是保存在后端的,通過權(quán)限判斷加載用戶可訪問的資源形成樹結(jié)構(gòu)返回給前端使用。leaf標明了這是一個目錄還是一個模塊,module_id對應的是控制器的路徑。 比如下面這個測試數(shù)據(jù)中。 "leaf": true, "module_id": "sys.UserController", 在app.js中,我們配置了appFolder:‘a(chǎn)pp/luter’, leaf標明了這是一個控制器模塊,點擊后會去觸發(fā)控制器加載動作。 所以這個模塊的實際路徑(也就是js文件)就是:${appFolder}/controller/${module_id}.js 即:app/luter/controller/sys.UserController.js
[ { "id": "111", "text": "系統(tǒng)管理", "href": null, "leaf": false, "iconCls": "fa fa-home", "module_id": "no sign", "qtip": "這個地方顯示鼠標懸停提示", "children": [ { "id": "11111", "text": "用戶管理", "href": null, "leaf": true, "iconCls": "fa fa-user", "module_id": "sys.UserController", "qtip": "系統(tǒng)用戶管理", "children": [] } ] } ]
導航菜單與tabpanel 聯(lián)動完成,下面弄個控制器實驗一下效果,以新建一個系統(tǒng)管理分類下的用戶管理模塊功能為例:
系統(tǒng)管理部分模塊放在sys目錄下,so:
控制器:app/luter/controller/sys/UserController.js
模型:app/luter/model/UserModel.js
Store:app/luter/store/UserStore.js
視圖主入口:app/luter/model/view/sys/user/User.js
列表視圖:app/luter/model/view/sys/user/UserList.js
......
用戶管理控制器 :app/luter/controller/sys/UserController.jsExt.define("luter.controller.sys.UserController", { extend: "Ext.app.Controller", stores: ["UserStore"], //用戶store views: ["sys.user.User"], //主view ,tab里會加載第一個視圖。 init: function () { this.control({ "userlistview": { "beforerender": function (view) { console.log("beforerender list...... "); }, "afterrender": function (view) { console.log("afterrender list...... "); // this.getUserStoreStore().load();//如果UserStore里沒設(shè)置autoLoad: true,就可以在這里加載用戶數(shù)據(jù) } } }); } });用戶模型Model:app/luter/model/UserModel.js
Ext.define("luter.model.UserModel", { extend: "Ext.data.Model", fields: [ {name: "id", type: "string"}, {name: "username", type: "string"}, {name: "gender", type: "string"}, {name: "real_name", type: "string"} ] });用戶Store:app/luter/store/UserStore.js
Ext.define("luter.store.UserStore", { extend: "Ext.data.Store", autoLoad: true,//自動加載數(shù)據(jù) model: "luter.model.UserModel",//使用的模型 pageSize: 15,//每頁數(shù)據(jù)多少 proxy: { type: "ajax",//ajax獲取數(shù)據(jù) actionMethods: { create: "POST", read: "POST", update: "POST", destroy: "POST" }, api: { read: "app/testdata/user.json"http://從這個地方獲取數(shù)據(jù),當然,這里用測試數(shù)據(jù) }, reader: {//返回數(shù)據(jù)解析器 type: "json", root: "root",//用戶列表數(shù)據(jù)在這個字段下 successProperty: "success",//成功與失敗的標志位是這個字段 totalProperty: "total"http://記錄總數(shù)在這個字段 }, listeners: { exception: function (proxy, response, operation, eOpts) { DealAjaxResponse(response);//監(jiān)聽ajax異常提示錯誤 } } }, remoteSort: true,//服務器端排序 sortOnLoad: true,//加載就排序 sorters: {//拿ID排序 property: "id", direction: "DESC" } });用戶管理模塊主視圖:app/luter/model/view/sys/user/User.js
Ext.define("luter.view.sys.user.User", { extend: "Ext.panel.Panel", alias: "widget.userview", layout: "fit", requires: ["luter.view.sys.user.UserList"],//引入用戶列表模塊 border: false, initComponent: function () { var me = this; me.items = [{ xtype: "userlistview", layout: "fit" }] me.callParent(arguments); } });用戶列表視圖:app/luter/model/view/sys/user/UserList.js
Ext.define("luter.view.sys.user.UserList", { extend: "Ext.grid.Panel", alias: "widget.userlistview",//其他地方就可以這么用:xtype:‘userlistview’ requires: [], store: "UserStore",//用到的store itemId: "userGrid",//自己的itemid columnLines: true,//是否顯示表格線 viewConfig: { emptyText: "暫無數(shù)據(jù)"http://store沒數(shù)據(jù)的時候顯示這個 }, initComponent: function () { var me = this; me.columns = [{ xtype: "rownumberer", text: "序號", width: 60 }, { header: "操作", xtype: "actioncolumn", width: 60, sortable: false, items: [{ text: "刪除", iconCls: "icon-delete", tooltip: "刪除這條記錄", handler: function (grid, rowIndex, colIndex) { var record = grid.getStore().getAt(rowIndex); if (!record) { toast({ msg: "請選中一條要刪除的記錄" }) } else { showConfirmMesg({ message: "確定刪除這條記錄?", fn: function (btn) { if (btn === "yes") { Ext.Ajax.request({ url: "sys/user/delete", method: "POST", params: { id: record.get("id") }, success: function (response, options) { DealAjaxResponse(response); Ext.data.StoreManager.lookup("User").load(); }, failure: function (response, options) { DealAjaxResponse(response); } }); } else { return false; } } }) } } }] }, { header: baseConfig.model.user.id, dataIndex: "id", hidden: false, flex: 1 }, { header: baseConfig.model.user.username, dataIndex: "username", flex: 1 }, { header: baseConfig.model.user.real_name, dataIndex: "real_name", flex: 1 } ] me.bbar = Ext.create("Ext.PagingToolbar", { store: me.store, displayInfo: true, displayMsg: "當前數(shù)據(jù) {0} - {1} 總數(shù): {2}", emptyMsg: "沒數(shù)據(jù)顯示", plugins: [new Ext.create("luter.ux.grid.PagingToolbarResizer", { options: [5, 10, 15, 20, 25, 50, 100] })] }) me.dockedItems = [{ xtype: "toolbar", items: [{ text: "添加", iconCls: baseConfig.appicon.add, tooltip: "添加", handler: function () { var win = Ext.create("luter.view.sys.user.UserAdd"); win.loadView(); win.show(); } }] }] me.listeners = { "itemdblclick": function (table, record, html, row, event, opt) { if (record) { var id = record.get("id"); var view = Ext.create("luter.view.sys.user.UserEdit", {title: "編輯數(shù)據(jù)"}); view.loadView(); loadFormDataFromDb(view, "sys/user/view?id=" + id); } else { showFailMesg({ msg: "加載信息失敗,請確認。" }) } } } me.plugins = [] me.callParent(arguments); } }); //這里的baseConfig定義在公共配置文件config.js中,如下:公共配置參數(shù)定義文件:app/luter/config.js
別忘記在app.html中app.js之前引入這個文件。
/** * icon_prefix font字體前綴定義 * baseConfig 全局配置 */ var icon_prefix = " fa blue-color ", baseConfig = { /** * 全局常量定義 */ cons: { noimage: "app/resource/images/noimage.jpg", /** * 靜態(tài)服務器的地址 */ static_server: "" }, /** * 渲染器,對Boolean類型的表格列的顯示內(nèi)容進行渲染 */ renders: { trueText: "", falseText: "", cancel: "" }, /** * 圖標定義 */ appicon: { home: icon_prefix + "fa-home", add: icon_prefix + "fa-plus", update: icon_prefix + "fa-edit", trash: icon_prefix + "fa-trash", delete: icon_prefix + "fa-remove red-color", set_wallpaper: icon_prefix + "fa-image", setting: icon_prefix + "fa-gears", desktop: icon_prefix + "fa-desktop", pailie: icon_prefix + "fa-cubes", logout: icon_prefix + "fa-power-off", avatar: icon_prefix + "fa-photo", key: icon_prefix + "fa-key", user: icon_prefix + "fa-user", refresh: icon_prefix + "fa-refresh blue-color", close: icon_prefix + "fa-close", male: icon_prefix + "fa-male", female: icon_prefix + "fa-female", role: icon_prefix + "fa-users", user_add: icon_prefix + "fa-user-plus", undo: icon_prefix + "fa-undo", search: icon_prefix + "fa-search", reset: icon_prefix + "fa-retweet", yes: icon_prefix + "fa-check green-color", no: icon_prefix + "fa-close red-color", list_ol: icon_prefix + " fa-list-ol", list_alt: icon_prefix + " fa-list-alt", ban: icon_prefix + "fa-ban", log: icon_prefix + "fa-tty", printer: icon_prefix + "fa-print", fax: icon_prefix + "fa-fax", download: icon_prefix + "fa-cloud-download", upload: icon_prefix + "fa-cloud-upload", comment: icon_prefix + " fa-commenting-o", credit: icon_prefix + "fa fa-gift" }, /** * 模型定義 */ model: { /** * 系統(tǒng)用戶模型 */ user: { id: "ID", username: "用戶名", real_name: "真實姓名" } } };
最后,附上用戶列表的測試數(shù)據(jù)(當然,瞎編的......):app/testdata/user.json
{ "total": 33, "root": [ { "id": "aaa", "username": "user", "real_name": "用戶" }, { "id": "ccc", "username": "user", "real_name": "用戶" }, { "id": "ffffd", "username": "user", "real_name": "用戶" }, { "id": "eee", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" }, { "id": "fff", "username": "user", "real_name": "用戶" } ], "success": true }
如上,沒問題的話,刷新頁面,應該能看到如下所示:
上圖中,一些Extjs默認的樣式經(jīng)過了hack。不是默認樣式。
最終,整個項目的目錄結(jié)構(gòu)如下:
1、打開chrome的開發(fā)控制臺,切換到network面板的js下。
2、刷新頁面
3、重復點擊左側(cè)用戶管理,查看JS加載情況。正常情況下同一個模塊的js只加載一次。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/92699.html
摘要:結(jié)構(gòu)實踐三完善基本頁面一般經(jīng)典的后臺管理系統(tǒng),都是左側(cè)菜單右側(cè)結(jié)構(gòu)布局。不免俗,咱也這么實現(xiàn)定義左側(cè)導航菜單新建采用的組件構(gòu)建一個導航菜單為了顯示圖標,引入字體圖標,在引入引入定義導航菜單數(shù)據(jù)功能菜單展開節(jié)點。 extjs-mvc結(jié)構(gòu)實踐(三):完善基本頁面2 一般經(jīng)典的后臺管理系統(tǒng),都是左側(cè)菜單右側(cè)tabs結(jié)構(gòu)布局。不免俗,咱也這么實現(xiàn)! 定義左側(cè)導航菜單 新建:app/luter/...
摘要:上篇實現(xiàn)了基本的代碼架構(gòu),控制器動態(tài)加載功能以及一個基礎(chǔ)的頁面布局,本節(jié)開始,將陸續(xù)完善這個頁面。頁面底部區(qū)域,主要顯示版權(quán)信息等,也可以顯示個時間啥的。。。頭部和底部定義完畢后,需要在中引入對應位置。 上篇實現(xiàn)了基本的代碼架構(gòu),控制器動態(tài)加載功能以及一個基礎(chǔ)的頁面布局,本節(jié)開始,將陸續(xù)完善這個頁面。 目標 如前所述,我們的頁面包含這么幾個區(qū)域: header: UI頂部區(qū)域,顯示系...
摘要:接著來,上一篇搭建了基本的項目骨架,到最后,其實啥也沒看見。。。目標全屏顯示左側(cè)導航菜單,右側(cè)標簽頁切換操作內(nèi)容區(qū)域。一般模型與你后臺返回的數(shù)據(jù)結(jié)構(gòu)一一對應。給其他組件提供一致接口使用數(shù)據(jù)。整個構(gòu)成一個所謂的。 接著來,上一篇搭建了基本的項目骨架,到最后,其實啥也沒看見。。。書接上回,開始寫UI效果。 目標 全屏顯示、左側(cè)導航菜單,右側(cè)標簽頁切換操作內(nèi)容區(qū)域。包含header和foo...
摘要:今天開始,一點點記錄一下使用搭建一個基礎(chǔ)結(jié)構(gòu)的過程。沒辦法,記性差這種結(jié)構(gòu)的前端,主要是面向后臺信息管理系統(tǒng),可以最大限度的規(guī)范前端代碼結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)。 今天開始,一點點記錄一下使用extjs6.2.0搭建一個基礎(chǔ)MVC結(jié)構(gòu)的過程。沒辦法,記性差:)這種結(jié)構(gòu)的UI前端,主要是面向后臺信息管理系統(tǒng),可以最大限度的規(guī)范前端代碼結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)。做網(wǎng)站 或者手機端,這種方式全引入了extjs,...
閱讀 2568·2021-11-22 13:53
閱讀 4069·2021-09-28 09:47
閱讀 858·2021-09-22 15:33
閱讀 809·2020-12-03 17:17
閱讀 3315·2019-08-30 13:13
閱讀 2121·2019-08-29 16:09
閱讀 1176·2019-08-29 12:24
閱讀 2452·2019-08-28 18:14