摘要:根據(jù)模塊創(chuàng)建模塊失敗。在中,我們配置了標(biāo)明了這是一個(gè)控制器模塊,點(diǎn)擊后會(huì)去觸發(fā)控制器加載動(dòng)作。正常情況下同一個(gè)模塊的只加載一次。
前面幾篇文檔,我們基本實(shí)現(xiàn)了一個(gè)靜態(tài)的extjs頁(yè)面,本篇開始,實(shí)現(xiàn)左側(cè)導(dǎo)航樹與右側(cè)內(nèi)容的聯(lián)動(dòng),也就是點(diǎn)擊導(dǎo)航菜單,加載對(duì)應(yīng)模塊頁(yè)面和業(yè)務(wù)邏輯,實(shí)現(xiàn)js文件的按需加載。業(yè)務(wù)需求是這樣的:
左側(cè)的treelist,當(dāng)點(diǎn)擊某個(gè)節(jié)點(diǎn)的時(shí)候,系統(tǒng)根據(jù)tree數(shù)據(jù)里配置的模塊信息,加載這個(gè)模塊,并且把模塊對(duì)應(yīng)的主頁(yè)面顯示在中間區(qū)域的tabpanel里。
改造主控制器:app/luter/controller/MainController.js監(jiān)聽導(dǎo)航樹的node點(diǎn)擊事件,進(jìn)行后續(xù)處理:
"navlist": { "itemclick":function(el, record, opt){ //可以通過如下方式獲取點(diǎn)擊節(jié)點(diǎn)的數(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的初始化事件,可以做點(diǎn)其他事情在這里,如有必要,記得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;//當(dāng)前點(diǎn)擊節(jié)點(diǎn)的數(shù)據(jù) var tabpanel = Ext.getCmp("systabpanel");//中間tabpanel var tabcount = tabpanel.items.getCount();//當(dāng)前tabpanel已經(jīng)打開幾個(gè)tab了。 var maxTabCount = 5;//最大打開的tab個(gè)數(shù) if (tabcount && tabcount > 5) { showFailMesg({ title: "為了更好的使用,最多允許打開5個(gè)頁(yè)面", msg: "您打開的頁(yè)面過多,請(qǐng)關(guān)掉一些!" }); return false; } if (nodeData.leaf) {//是打開新模塊,否則是展開樹節(jié)點(diǎn) var moduleID = nodeData.module_id;//找到控制器ID,定義在tree的數(shù)據(jù)里modole_id if (!moduleID || moduleID == "") { showFailMesg({ title: "創(chuàng)建模塊失敗.", msg: "模塊加載錯(cuò)誤,模塊id為空,創(chuàng)建模塊失敗" }); return false; } console.log("to add module with id:" + moduleID); //開始加載控制器 try { //嘗試加載這個(gè)控制器,這個(gè)過程就是按需ajax加載js文件的過程。 //如果這個(gè)模塊被加載過,則不會(huì)重復(fù)加載。 var module = luterapp.getController(moduleID); } catch (error) { showFailMesg({ msg: "根據(jù)模塊ID:" + moduleID + "創(chuàng)建模塊失敗。" + "左側(cè)菜單樹對(duì)應(yīng)的測(cè)試數(shù)據(jù):app/testdata/menu.json
可能的原因 :
1、該模塊當(dāng)前沒有實(shí)現(xiàn)." + "
2、模塊文件名稱與模塊名稱不一致,請(qǐng)檢查" + "Error: " + error + "" }); return false; } finally { } //判斷模塊是否加載下來,因?yàn)槭莂jax加載,所以還是判斷一下比較好 if (!module) { showFailMesg({ msg: "B:load module fail,the module object is null." + "
maybe :the module is Not available now." }); return false; } //加載到之后,默認(rèn)去獲取控制器里views:[]數(shù)組里的第一個(gè)作為主視圖 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; } //判斷一下這個(gè)視圖是不是已經(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) {//不存在新建 //不管是啥,都放到一個(gè)panel里面。 notab = tabpanel.add(Ext.create("Ext.panel.Panel", { tooltip: nodeData.text + ":" + nodeData.qtip, id: tabid, // tab的唯一id title: nodeData.text, // tab的標(biāo)題 layout: "fit", // 填充布局,它不會(huì)讓load進(jìn)來的東西改變大小 border: false, // 無邊框 closable: true, // 有關(guān)閉選項(xiàng)卡按鈕 iconCls: nodeData.iconCls, listeners: { // 偵聽tab頁(yè)被激活里觸發(fā)的動(dòng)作 scope: this, destroy: function () { console.log("tab :" + tabid + ",has been destroyed") } }, items: [view.create()] })); //新建之后focus tabpanel.setActiveTab(notab); } else {//如果這個(gè)tab已經(jīng)存在了,則focus到這個(gè)tab tabpanel.setActiveTab(notab); } } else { //如果leaf =false,則說明這不是一個(gè)最底層節(jié)點(diǎn),是目錄,展開。 console.log("tree node expand") } } } }); }, //這個(gè)方法從tab id里分離出控制器名稱 getTabId: function (mid) { var winid = mid; var c = winid.split("."); winid = c.pop(); return winid + "-tab"; } });
一般情況下,這個(gè)菜單數(shù)據(jù)是保存在后端的,通過權(quán)限判斷加載用戶可訪問的資源形成樹結(jié)構(gòu)返回給前端使用。leaf標(biāo)明了這是一個(gè)目錄還是一個(gè)模塊,module_id對(duì)應(yīng)的是控制器的路徑。 比如下面這個(gè)測(cè)試數(shù)據(jù)中。 "leaf": true, "module_id": "sys.UserController", 在app.js中,我們配置了appFolder:‘a(chǎn)pp/luter’, leaf標(biāo)明了這是一個(gè)控制器模塊,點(diǎn)擊后會(huì)去觸發(fā)控制器加載動(dòng)作。 所以這個(gè)模塊的實(shí)際路徑(也就是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": "這個(gè)地方顯示鼠標(biāo)懸停提示", "children": [ { "id": "11111", "text": "用戶管理", "href": null, "leaf": true, "iconCls": "fa fa-user", "module_id": "sys.UserController", "qtip": "系統(tǒng)用戶管理", "children": [] } ] } ]
導(dǎo)航菜單與tabpanel 聯(lián)動(dòng)完成,下面弄個(gè)控制器實(shí)驗(yàn)一下效果,以新建一個(gè)系統(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里會(huì)加載第一個(gè)視圖。 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,//自動(dòng)加載數(shù)據(jù) model: "luter.model.UserModel",//使用的模型 pageSize: 15,//每頁(yè)數(shù)據(jù)多少 proxy: { type: "ajax",//ajax獲取數(shù)據(jù) actionMethods: { create: "POST", read: "POST", update: "POST", destroy: "POST" }, api: { read: "app/testdata/user.json"http://從這個(gè)地方獲取數(shù)據(jù),當(dāng)然,這里用測(cè)試數(shù)據(jù) }, reader: {//返回?cái)?shù)據(jù)解析器 type: "json", root: "root",//用戶列表數(shù)據(jù)在這個(gè)字段下 successProperty: "success",//成功與失敗的標(biāo)志位是這個(gè)字段 totalProperty: "total"http://記錄總數(shù)在這個(gè)字段 }, listeners: { exception: function (proxy, response, operation, eOpts) { DealAjaxResponse(response);//監(jiān)聽ajax異常提示錯(cuò)誤 } } }, remoteSort: true,//服務(wù)器端排序 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ù)的時(shí)候顯示這個(gè) }, initComponent: function () { var me = this; me.columns = [{ xtype: "rownumberer", text: "序號(hào)", 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: "請(qǐng)選中一條要?jiǎng)h除的記錄" }) } 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: "當(dāng)前數(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: "加載信息失敗,請(qǐng)確認(rèn)。" }) } } } me.plugins = [] me.callParent(arguments); } }); //這里的baseConfig定義在公共配置文件config.js中,如下:公共配置參數(shù)定義文件:app/luter/config.js
別忘記在app.html中app.js之前引入這個(gè)文件。
/** * icon_prefix font字體前綴定義 * baseConfig 全局配置 */ var icon_prefix = " fa blue-color ", baseConfig = { /** * 全局常量定義 */ cons: { noimage: "app/resource/images/noimage.jpg", /** * 靜態(tài)服務(wù)器的地址 */ static_server: "" }, /** * 渲染器,對(duì)Boolean類型的表格列的顯示內(nèi)容進(jìn)行渲染 */ renders: { trueText: "", falseText: "", cancel: "" }, /** * 圖標(biāo)定義 */ 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í)姓名" } } };
最后,附上用戶列表的測(cè)試數(shù)據(jù)(當(dāng)然,瞎編的......):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 }
如上,沒問題的話,刷新頁(yè)面,應(yīng)該能看到如下所示:
上圖中,一些Extjs默認(rèn)的樣式經(jīng)過了hack。不是默認(rèn)樣式。
最終,整個(gè)項(xiàng)目的目錄結(jié)構(gòu)如下:
1、打開chrome的開發(fā)控制臺(tái),切換到network面板的js下。
2、刷新頁(yè)面
3、重復(fù)點(diǎn)擊左側(cè)用戶管理,查看JS加載情況。正常情況下同一個(gè)模塊的js只加載一次。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/92699.html
摘要:結(jié)構(gòu)實(shí)踐三完善基本頁(yè)面一般經(jīng)典的后臺(tái)管理系統(tǒng),都是左側(cè)菜單右側(cè)結(jié)構(gòu)布局。不免俗,咱也這么實(shí)現(xiàn)定義左側(cè)導(dǎo)航菜單新建采用的組件構(gòu)建一個(gè)導(dǎo)航菜單為了顯示圖標(biāo),引入字體圖標(biāo),在引入引入定義導(dǎo)航菜單數(shù)據(jù)功能菜單展開節(jié)點(diǎn)。 extjs-mvc結(jié)構(gòu)實(shí)踐(三):完善基本頁(yè)面2 一般經(jīng)典的后臺(tái)管理系統(tǒng),都是左側(cè)菜單右側(cè)tabs結(jié)構(gòu)布局。不免俗,咱也這么實(shí)現(xiàn)! 定義左側(cè)導(dǎo)航菜單 新建:app/luter/...
摘要:上篇實(shí)現(xiàn)了基本的代碼架構(gòu),控制器動(dòng)態(tài)加載功能以及一個(gè)基礎(chǔ)的頁(yè)面布局,本節(jié)開始,將陸續(xù)完善這個(gè)頁(yè)面。頁(yè)面底部區(qū)域,主要顯示版權(quán)信息等,也可以顯示個(gè)時(shí)間啥的。。。頭部和底部定義完畢后,需要在中引入對(duì)應(yīng)位置。 上篇實(shí)現(xiàn)了基本的代碼架構(gòu),控制器動(dòng)態(tài)加載功能以及一個(gè)基礎(chǔ)的頁(yè)面布局,本節(jié)開始,將陸續(xù)完善這個(gè)頁(yè)面。 目標(biāo) 如前所述,我們的頁(yè)面包含這么幾個(gè)區(qū)域: header: UI頂部區(qū)域,顯示系...
摘要:接著來,上一篇搭建了基本的項(xiàng)目骨架,到最后,其實(shí)啥也沒看見。。。目標(biāo)全屏顯示左側(cè)導(dǎo)航菜單,右側(cè)標(biāo)簽頁(yè)切換操作內(nèi)容區(qū)域。一般模型與你后臺(tái)返回的數(shù)據(jù)結(jié)構(gòu)一一對(duì)應(yīng)。給其他組件提供一致接口使用數(shù)據(jù)。整個(gè)構(gòu)成一個(gè)所謂的。 接著來,上一篇搭建了基本的項(xiàng)目骨架,到最后,其實(shí)啥也沒看見。。。書接上回,開始寫UI效果。 目標(biāo) 全屏顯示、左側(cè)導(dǎo)航菜單,右側(cè)標(biāo)簽頁(yè)切換操作內(nèi)容區(qū)域。包含header和foo...
摘要:今天開始,一點(diǎn)點(diǎn)記錄一下使用搭建一個(gè)基礎(chǔ)結(jié)構(gòu)的過程。沒辦法,記性差這種結(jié)構(gòu)的前端,主要是面向后臺(tái)信息管理系統(tǒng),可以最大限度的規(guī)范前端代碼結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)。 今天開始,一點(diǎn)點(diǎn)記錄一下使用extjs6.2.0搭建一個(gè)基礎(chǔ)MVC結(jié)構(gòu)的過程。沒辦法,記性差:)這種結(jié)構(gòu)的UI前端,主要是面向后臺(tái)信息管理系統(tǒng),可以最大限度的規(guī)范前端代碼結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)。做網(wǎng)站 或者手機(jī)端,這種方式全引入了extjs,...
閱讀 2752·2021-11-22 13:53
閱讀 4334·2021-09-28 09:47
閱讀 1037·2021-09-22 15:33
閱讀 1016·2020-12-03 17:17
閱讀 3454·2019-08-30 13:13
閱讀 2268·2019-08-29 16:09
閱讀 1319·2019-08-29 12:24
閱讀 2593·2019-08-28 18:14