ExtJS 4 组件化编程,动态加载,面向对象,Direct结合成功,目前为止我的最佳实践
http://www.cnblogs.com/luyingxue/archive/2011/05/22/2053318.html
?
ExtJS4中支持组件化编程和Direct,官方实例中分别提供了两种技术的示例,但没有两种方式结合的例子,经多次测试,由于4.0中存在的bug(暂时这么认为,也许是我水平烂),两种方式结合会产生一系列问题,在静态加载、动态加载、Direct结合的过程中(尤其是采用Direct的时候,用url不会出错),经常性的报错。
官方论坛也没有相关资料,中文也没找到。
分析2天源代码+调试+测试各种结合方式(new/define/create/各参数调节),终于找到一个稳定运行的实现方式,也很好的体现了面向对象及组件化编程的思想。示例如下,相关解释卸载注释中,注意此示例必须结合ExtJS4运行。
代码如下:
1、html页(关键部分代码)
1 <!--加载ExtJS的CSS和js,也可以只加载核心包,然后按照提示加载需要的js(未测试)--> 2 <!--其他js全部使用动态加载,在head部分不需要引用js--> 3 <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css" /> 4 ? <link rel="stylesheet" type="text/css" href="css/application.css" /> 5 ? <script src="ext/ext-all.js" type="text/javascript"></script> 6 ? <script src="ext/ext-lang-zh_CN.js" type="text/javascript"></script> 7 ? <!--本例中使用.Net,此处加载Direct的Api--> 8 <script src="Api.ashx" type="text/javascript"></script> 9 <script type="text/javascript">10 //以下设置必须在Ext.onReady之前11 ? //动态配置打开12 ? Ext.Loader.setConfig({enabled: true});13 //设置组件路径14 ? Ext.Loader.setPath('App', 'js');15 //加载MainViewport组件,注意MainViewport里面需要的js不需要在此加载,在MainViewport的define中用requires参数定义就可以,其他组件类似16 ? //每种组件只需要考虑自己的require即可17 ? Ext.require([18 'App.MainViewport'19 ]);20 //加入Direct的Provider21 ? Ext.direct.Manager.addProvider(Ext.app.USER_API);22 Ext.onReady(function () {23 Ext.QuickTips.init();24 Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));25 //舍弃new函数,改用Ext.create26 ? Ext.create(App.MainViewport);27 setTimeout(function () {28 Ext.get('loading').remove();29 Ext.get('loading-mask').fadeOut({ remove: true });30 Ext.getCmp('MainLicense').collapse();31 }, 250);32 });33 </script>
2、MainViewport.js(定义App.MainViewport类,由于指定了路径,这个js文件必须放在js目录下,而且文件名称必须是MainViewport.js,否则无法加载)
1 //组件名称、js路径、js文件名必须匹配 2 ?Ext.define('App.MainViewport',{ 3 //加载MainViewport内的各组件 4 requires:['App.MainFunctionPanel','App.Banner','App.Licence'], 5 extend:'Ext.Viewport', 6 layout: 'border', 7 items: [ 8 //使用xtype定义items,利用id和Ext.getCmp获取相应的对象,或者通过itemId和getComponent()获取对象,注意scope的不同 9 {xtype: 'Banner',itemId: 'MainBanner',region: 'north',margins: '0 0 0 5'},10 {xtype: 'Licence',id: 'MainLicense',region: 'south',margins: '0 0 0 0',contentEl: 'south'}, 11 {xtype:'MainFunctionPanel',region: 'west'},12 //也可以使用Ext.create创建对象,但不要使用new13 Ext.create('Ext.tab.Panel', {14 region: 'center',15 id:'mainTabPanel',16 deferredRender: false,17 activeTab: 0,18 items: [{19 id:'mainFilePanel',20 title: '文件浏览',21 autoScroll: true,22 listeners: {23 activate: function () { Ext.getCmp('mainFunctionFile').expand() }24 }25 },{26 id:'mainSearchPanel',27 title: '文件查找',28 autoScroll: true,29 listeners: {30 activate: function () { Ext.getCmp('mainFunctionSearch').expand() }31 }32 }]33 })]34 });
3、App.MainFunctionPanel类,放置的位置参照以上
1 //MainFunctionPanel类,继承Ext.Panel 2 Ext.define('App.MainFunctionPanel',{ 3 extend:'Ext.Panel', 4 requires:'App.MainFunctionTree', 5 alias:'widget.MainFunctionPanel', 6 title: '功能选择', 7 split: true, 8 width: 200, 9 minWidth: 175,10 maxWidth: 400,11 collapsible: true,12 animCollapse: true,13 margins: '0 0 0 5',14 layout: 'accordion',15 items: [16 {17 xtype:'FunctionTree',18 title: '文件浏览',19 id:'mainFunctionFile',20 iconCls: 'nav', // see the HEAD section for style used21 listeners: {22 //beforerender: function () { alert('beforerender'); },23 //beforecollapse: function () { alert('beforecollapse'); },24 //beforeexpand: function () { alert('beforeexpand'); },25 expand: function () { Ext.getCmp('mainTabPanel').setActiveTab(Ext.getCmp('mainFilePanel')); }26 }27 }, {28 title: '文件查找',29 id:'mainFunctionSearch',30 html: '<p>Some settings in here.</p>',31 iconCls: 'settings',32 listeners: {33 //beforerender: function () { alert('beforerender'); },34 //beforecollapse: function () { alert('beforecollapse'); },35 //beforeexpand: function () { alert('beforeexpand'); },36 expand: function () { Ext.getCmp('mainTabPanel').setActiveTab(Ext.getCmp('mainSearchPanel')); }37 }38 }, {39 title: '系统管理',40 id:'mainFunctionAdmin',41 html: '<p>Some info in here.</p>',42 iconCls: 'info',43 listeners: {44 //beforerender: function () { alert('beforerender'); },45 //beforecollapse: function () { alert('beforecollapse'); },46 //beforeexpand: function () { alert('beforeexpand'); },47 expand: function () { Ext.MessageBox.alert('消息', '系统管理展开了!'); }48 }49 }]50 });
4、App.MainFunctionTree
1 Ext.define('FunctionTreeStore', { 2 extend: 'Ext.data.TreeStore', 3 autoLoad: true, 4 proxy:{ 5 type: 'direct', 6 //设置Direct服务函数 7 directFn: MyApp.TestAction.getTree, 8 paramOrder: ['node'] 9 },10 root:{11 expanded : true12 }13 });14 Ext.define('App.MainFunctionTree',{15 extend:'Ext.tree.Panel',16 alias:'widget.FunctionTree',17 store: Ext.create('FunctionTreeStore'),18 height: 350,19 width: 600,20 rootVisible: false21 22 });
服务器Direct照以往的写就ok,利用DirectHandler.Configure(DirectProvider provider, IEnumerable<object> items)加载相应的服务Class
5、Api.ashx
1 <%@ WebHandler Language="C#" Class="Api" %> 2 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Web; 7 using Ext.Direct; 8 9 public class Api : DirectHandler10 {11 12 public override string ProviderName13 {14 get15 {16 return "Ext.app.USER_API";17 }18 }19 20 public override string Namespace21 {22 get23 {24 return "MyApp";25 }26 }27 28 protected override void ConfigureProvider(DirectProvider provider)29 {30 this.Configure(provider, new object[] { new CheckLogin(),new TestAction() });31 }32 33 }
6、随手写的生成树状图的cs,怎一个烂字了得……
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using Ext.Direct; 6 using Newtonsoft.Json; 7 using Newtonsoft.Json.Linq; 8 using System.Web.SessionState; 9 using System.Web.Security;10 11 /// <summary>12 ///CheckLogin 的摘要说明13 /// </summary>14 [DirectAction]15 public class TestAction16 {17 18 [DirectMethod]19 public JArray getTree(string id)20 {21 JArray data = new JArray();22 23 data.Add(new JObject(24 new JProperty("id", id+id),25 new JProperty("text", "tes"),26 new JProperty("leaf", false)27 ));28 29 30 return data;31 }32 }