Extjs 模块化动态加载js实践

文章分类:Web前端

前一段转载了一篇

透明加载外部 javascript 文件函数

挺有启发的,觉得可以套用在extjs的管理上,管理界面 两栏布局,左边栏一棵菜单树,右面一个tabpanel,菜单树的每个菜单代表一个模块,每个模块用一个js来实现,需要时载入就行了,而不需要刚开始时把所有的模块都载进入


当点击菜单树的节点时调用:

 

Js代码
  1. function openGetBugsPanel(name) {  
  2.     var moduleId = 'BugList_tab';  
  3.     //一个静态方法,表示从一个js载入了一个新的模块  
  4.     Ext.ux.yiminghe.framework.core.newModule(  
  5.     {  
  6.         //模块的id       
  7.         moduleId: moduleId,  
  8.         //在哪个tabpanel新加一个模块   
  9.         tabPanel: window.tabs,  
  10.         //模块所在js  
  11.         moduleURL: 'js/modules/Bugs.js',  
  12.         //模块所需要的参数  
  13.         moduleParams: {  
  14.             title: name,  
  15.             MYBugs: false  
  16.         },  
  17.         //如果该模块已经在tabpanel上了,怎么处理             
  18.         existCallBack: function(panel) {  
  19.             panel.setTitle(name);  
  20.             panel.filters.clearFilters();  
  21.         }  
  22.     }  
  23.     );  
  24. }  
 

 

其实每个模块就是一个panel,加入到tabpanel 就行了,关键是要 动态构造这个panel

例如这个bugs.js

 

Js代码
  1. /** 
  2.     ajax 直接返回一个类,eval ,new 
  3. **/  
  4. Ext.extend(Ext.Panel, {  
  5.     initComponent: function() {  
  6.   
  7.         var bugsGrid_metaData = [  
  8.         {  
  9.             dataIndex: 'projectId',  
  10.             header: '项目',  
  11.             width: 70,  
  12.             sortable: true,  
  13.             show: true  
  14.         },  
  15.         {  
  16.             dataIndex: 'moduleId',  
  17.             header: '模块',  
  18.             width: 70,  
  19.             sortable: true,  
  20.             show: true  
  21.         },  
  22.         {  
  23.             dataIndex: 'bid',  
  24.             header: 'Bug/Task编号',  
  25.             sortable: true,  
  26.             width: 100  
  27.         },  
  28.         {  
  29.             dataIndex: 'btitle',  
  30.             header: 'Bug/Task标题',  
  31.             width: 250,  
  32.             sortable: true,  
  33.             show: true  
  34.   
  35.         },  
  36.         {  
  37.             dataIndex: 'degree',  
  38.             header: '严重程度',  
  39.             width: 100,  
  40.             sortable: true,  
  41.             show: true,  
  42.             renderer: function(val) {  
  43.                 return '<span style="color:green">' + val + '</span> ';  
  44.             }  
  45.         },  
  46.         {  
  47.             dataIndex: 'status',  
  48.             header: '状态',  
  49.             width: 70,  
  50.             show: true,  
  51.             sortable: true,  
  52.             renderer: function(val) {  
  53.   
  54.   
  55.                 return '<span style="color:red">' + val + '</span> ';  
  56.             }  
  57.         },  
  58.         {  
  59.             dataIndex: 'who',  
  60.             header: '由谁创建',  
  61.             width: 70,  
  62.             sortable: true,  
  63.             show: true  
  64.         },  
  65.         {  
  66.             dataIndex: 'assign',  
  67.             header: '指派给谁',  
  68.             width: 70,  
  69.             sortable: true,  
  70.             show: true  
  71.         },  
  72.         {  
  73.             dataIndex: 'resolve',  
  74.             header: '由谁解决',  
  75.             width: 70,  
  76.             sortable: true,  
  77.             show: true  
  78.         },  
  79.         {  
  80.             dataIndex: 'moduleId',  
  81.             header: 'moduleId',  
  82.             sortable: true,  
  83.             width: 70  
  84.         },  
  85.         {  
  86.             dataIndex: 'method',  
  87.             header: '解决方案',  
  88.             width: 100,  
  89.             sortable: true,  
  90.             show: true  
  91.         },  
  92.         {  
  93.             dataIndex: 'openedTime',  
  94.             header: '提交时间',  
  95.             width: 150,  
  96.             sortable: true,  
  97.             show: true,  
  98.             renderer: function(val) {  
  99.   
  100.                 var d = new Date();  
  101.                 d.setTime(val);  
  102.                 return '<span style="color:red">' + d.toLocaleString() + '</span> ';  
  103.             }  
  104.         }  
  105.         ];  
  106.   
  107.         Ext.grid.filter.StringFilter.prototype.icon = 'desktop/js/filter/img/find.png';  
  108.         this.filters = new Ext.grid.GridFilters({  
  109.             filters: [  
  110.             {  
  111.                 type: 'list',  
  112.                 dataIndex: 'projectId',  
  113.                 single: true,  
  114.                 options: PROJECTS,  
  115.                 phpMode: true,  
  116.                 listeners: {  
  117.                     'update'function() {  
  118.                         var pid = this.getValue();  
  119.                         if (pid == ''return;  
  120.                         // 实例化Ext发送Ajax请求需要的Connection对象  
  121.                         var conn = new Ext.data.Connection();  
  122.                         // 发送异步请求  
  123.                         conn.request({  
  124.                             // 请求地址  
  125.                             url: 'bug/get_modules_ext.jsp?project_id=' + pid,  
  126.                             method: 'GET',  
  127.                             // 指定回调函数  
  128.                             callback: callback  
  129.                         });  
  130.                         //回调函数  
  131.                         function callback(options, success, response) {  
  132.                             if (success) {  
  133.                                 // 如果成功则使用Ext将JSON字符串转换为JavaScript对象  
  134.                                 var jsonObj = Ext.util.JSON.decode(response.responseText);  
  135.                                 // 到这就可以取你想要的东东了  
  136.                                 //  取消息id  
  137.                                 var m_data = jsonObj.data;  
  138.                                 filters.getFilter(1).options = m_data;  
  139.                                 filters.getFilter(1).store.loadData(m_data);  
  140.                             } else {  
  141.                                 alert(response.responseText);  
  142.                             }  
  143.   
  144.                         }  
  145.                     }  
  146.                 }  
  147.             },  
  148.             {  
  149.                 type: 'list',  
  150.                 dataIndex: 'moduleId',  
  151.                 single: true,  
  152.                 options: [],  
  153.                 phpMode: true  
  154.             },  
  155.             {  
  156.                 type: 'string',  
  157.                 dataIndex: 'btitle'  
  158.             },  
  159.   
  160.             {  
  161.                 type: 'list',  
  162.                 dataIndex: 'assign',  
  163.                 single: true,  
  164.                 //id:'assign_filter',  
  165.                 options: USERS,  
  166.                 phpMode: true  
  167.             },  
  168.             {  
  169.                 type: 'list',  
  170.                 dataIndex: 'who',  
  171.                 single: true,  
  172.                 options: USERS,  
  173.                 phpMode: true  
  174.             },  
  175.   
  176.             {  
  177.                 type: 'list',  
  178.                 dataIndex: 'resolve',  
  179.                 single: true,  
  180.                 options: USERS,  
  181.                 phpMode: true  
  182.             },  
  183.             {  
  184.                 type: 'list',  
  185.                 dataIndex: 'status',  
  186.                 single: true,  
  187.                 //id:'status_filter',  
  188.                 options: BUGSTATUSES,  
  189.                 phpMode: true  
  190.             }  
  191.             ]  
  192.         });  
  193.   
  194.         var gridMenuDatas = [  
  195.         {  
  196.             text: '提交Bug/Task',  
  197.             iconCls: 'badd',  
  198.             handler: function() {  
  199.                 addBugFormPanel('提交Bug/Task');  
  200.             }  
  201.         },  
  202.         '-',  
  203.         {  
  204.             text: '编辑',  
  205.             iconCls: 'bedit',  
  206.             handler: function() {  
  207.                 var record = this.getSelectionRecord();  
  208.                 createEditBugForm(record.get('bid'), record.get('btitle'));  
  209.             }  
  210.         }  
  211.         ,  
  212.         '-',  
  213.         {  
  214.             text: '解决',  
  215.             iconCls  
  216.             :  
  217.             'bok',  
  218.             handler  
  219.             :  
  220.             function() {  
  221.                 var record = this.getSelectionRecord();  
  222.                 createResolveBugForm(record.get('bid'), record.get('btitle'), record.get('moduleId'));  
  223.             }  
  224.         }  
  225.         ,  
  226.         '-',  
  227.         {  
  228.             text: '历史',  
  229.             iconCls: 'bsearch',  
  230.             handler: function() {  
  231.                 var record = this.getSelectionRecord();  
  232.                 var moduleId = 'bugHistory_Tab' + record.get('bid');  
  233.                 var realId = 'bugHistory_Tab' + record.get('bid');  
  234.                 Ext.ux.yiminghe.framework.core.newModule(  
  235.                 {  
  236.                     moduleId: moduleId,  
  237.                     realId: realId,  
  238.                     tabPanel: window.tabs,  
  239.                     moduleURL: 'js/modules/BugHistories.js',  
  240.                     moduleParams: {  
  241.                         bugId: record.get('bid'),  
  242.                         bugName: record.get('btitle'),  
  243.                         moduleId: record.get('moduleId')  
  244.                     },  
  245.                     existCallBack: function(panel) {  
  246.                         panel.bugHistoryGrid.reload();  
  247.                     }  
  248.                 }  
  249.                 );  
  250.             }  
  251.         },  
  252.         {  
  253.             text: '链接地址',  
  254.             iconCls: 'blist',  
  255.             handler: function() {  
  256.                 var record = this.getSelectionRecord();  
  257.                 if (record)  
  258.                 Ext.MessageBox.alert(record.get('btitle') + ' - Bug地址', BASEPATH + '/bug/BtsBugDetail.jsp?bugId=' + record.get('bid'));  
  259.             }  
  260.         }  
  261.   
  262.         ];  
  263.         var gridContextMenuDatas = [  
  264.         gridMenuDatas[0], gridMenuDatas[2], gridMenuDatas[4], gridMenuDatas[6], gridMenuDatas[7]  
  265.         ];  
  266.         var dbClick_g = function(record) {  
  267.             var moduleId = 'bugHistory_Tab';  
  268.             var realId = 'bugHistory_Tab' + record.get('bid');  
  269.             Ext.ux.yiminghe.framework.core.newModule(  
  270.             {  
  271.                 moduleId: moduleId,  
  272.                 realId: realId,  
  273.                 tabPanel: window.tabs,  
  274.                 moduleURL: 'js/modules/BugHistories.js',  
  275.                 moduleParams: {  
  276.                     bugId: record.get('bid'),  
  277.                     bugName: record.get('btitle'),  
  278.                     moduleId: record.get('moduleId')  
  279.                 },  
  280.                 existCallBack: function(panel) {  
  281.                     panel.bugHistoryGrid.reload();  
  282.                 }  
  283.             }  
  284.             );  
  285.         };  
  286.         this.bugsGrid = new Ext.ux.yiminghe.JsonGridPanel({  
  287.             columns: bugsGrid_metaData,  
  288.             pageSize: 15,  
  289.             initload: true,  
  290.             plugins: [this.filters],  
  291.             viewConfig: {  
  292.                 forceFit: true,  
  293.                 autoFill: true  
  294.             },  
  295.             autoScroll: true,  
  296.             sm: new Ext.grid.RowSelectionModel(  
  297.             {  
  298.                 singleSelect: true  
  299.             }),  
  300.             dataSource: 'bug/BtsGetBugsDO_Ext.jsp',  
  301.             tbar: gridMenuDatas,  
  302.             stripeRows: true,  
  303.             border: false,  
  304.             bodyStyle: 'width:100%',  
  305.             isGroupHeader: false,  
  306.             rowcontextmenu: gridContextMenuDatas,  
  307.             doubleClick: dbClick_g,  
  308.             pageBarPlugins: [new Ext.ux.Andrie.pPageSize({  
  309.                 beforeText: '每页显示',  
  310.                 afterText: '条'  
  311.             })]  
  312.         });  
  313.         if (this.MYBugs) {  
  314.             this.filters.getFilter('assign').setValue(CURRENTUSERID);  
  315.             this.filters.getFilter('assign').setActive(truetrue);  
  316.             this.filters.getFilter('status').setValue(0);  
  317.             this.filters.getFilter('status').setActive(truetrue);  
  318.         } else {  
  319.   
  320.             this.filters.clearFilters();  
  321.             this.bugsGrid.reload();  
  322.         }  
  323.         Ext.apply(this, {  
  324.             title: this.title,  
  325.             iconCls: 'tabs',  
  326.             autoScroll: false,  
  327.             id: 'BugList_tab',  
  328.             layout: 'fit',  
  329.             items: this.bugsGrid,  
  330.             closable: true  
  331.         });  
  332.         //调用父类构造函数(必须)  
  333.         module.superclass.initComponent.apply(this, arguments);  
  334.     }  
  335. });  
   

可以看到在这个模块中可以调用 传过来的参数

 

 

Js代码
  1. {  
  2. title:name,  
  3. MYBugs:false  
  4. }  


现在关键是 newModule 的实现了 ,也很简单 ,就是 ajax把 模块类区过来 ,new 一下 就是一个新的模块了 不过要注意一下缓存这个模块类的定义

 

Js代码
  1. Ext.namespace("Ext.ux.yiminghe.framework.core");  
  2.   
  3. Ext.ux.yiminghe.framework.core.newModule = function(config) {  
  4.     //模块类的名字  
  5.     var moduleId = config.moduleId;  
  6.     //主Tab名字  
  7.     var tabPanel = config.tabPanel;  
  8.     //加载模块类的地址  
  9.     var moduleURL = config.moduleURL;  
  10.     //模块实例tab的id  
  11.     var realId = config.realId || moduleId;  
  12.     //缓存模块  
  13.     tabPanel.uxmodules = tabPanel.uxmodules || {};  
  14.     //模块实例的配置参数  
  15.     var moduleParams = config.moduleParams || {};  
  16.   
  17.     if (tabPanel.findById(realId)) {  
  18.         tabPanel.findById(realId).show();  
  19.         //如果已经载入该Tab ,则调用调整函数  
  20.         if (config.existCallBack)  
  21.         config.existCallBack(tabPanel.findById(realId));  
  22.         return;  
  23.     }  
  24.     if (tabPanel.uxmodules[moduleId]) {  
  25.         var module = tabPanel.uxmodules[moduleId];  
  26.         var moduleInstance = new module(moduleParams);  
  27.         var newCmp = tabPanel.add(moduleInstance);  
  28.         tabPanel.doLayout();  
  29.         tabPanel.setActiveTab(newCmp);  
  30.         return;  
  31.     }  
  32.     tabPanel.loadMask.show();  
  33.     Ext.Ajax.request(  
  34.     {  
  35.         method: 'GET',  
  36.         disableCaching: false,  
  37.         //utf-8 编码  
  38.         url: moduleURL,  
  39.         success: function(response) {  
  40.             var module = eval(response.responseText);  
  41.             tabPanel.uxmodules[moduleId] = module;  
  42.             var moduleInstance = new module(moduleParams);  
  43.             var newCmp = tabPanel.add(moduleInstance);  
  44.             tabPanel.doLayout();  
  45.             tabPanel.setActiveTab(newCmp);  
  46.             tabPanel.loadMask.hide();  
  47.         }  
  48.     }  
  49.     );  
  50. }  
 

 

总结一下流程:

 

1.请求一段 javascript 代码(定义一个Panel子类)

2.eval 出类型 T

3.得到新类型的实例 instance = new T
4.总控的tabpnel add instance 就可以了。