聊聊ExtJS
这几天接触了一个项目 前台用的是extjs 发现这个东西还是有点意思的 
就把前台的部分 剥离了下来 有兴趣的朋友可以当做模板学习

不多说先上效果图

一个ExtJs实例_html


这篇文章 可以看作是ext知识的一个汇总
因此我不想讲太多细碎的知识点 但我会一一之命这些知识点在哪里可以找到
另一方面 ext细碎的知识点确实太多 自己没有精力也不想搞的太清楚 够用就行
我会说一些 我认为最重要的部分
首先 希望大家看看这篇文章
关于ext的布局
在项目里 主要用到了两种布局 accordion BorderLayout
其次还有一个TabPanel 这个大家可以参考 (文库里面的第三页)
​​​http://wenku.baidu.com/link?url=NE2POFUVQ4QopprUDiRmgyj3McqpT8WOJ5yw7Rp59GGa56BBm1lB2aEiaZ-anxgghfm4hTYHpF9mMfLXQSgc92dUV-1B7x4qoxcnzG4Zv5u​​​
先看admin_main.jsp 页面如下


[html]  ​​view plain​


  1. <%@ page language="java" pageEncoding="UTF-8"%>

  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  3. <html>
  4. <head>
  5. <title>资源共享平台</title>
  6. <meta http-equiv="pragma" content="no-cache">
  7. <meta http-equiv="cache-control" content="no-cache">
  8. <meta http-equiv="expires" content="0">
  9. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  10. <meta http-equiv="description" content="This is my page">
  11. <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
  12. <link rel="stylesheet" type="text/css"
  13. href="ext/resources/css/ext-all.css" />
  14. <script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
  15. <script type="text/javascript" src="ext/ext-all.js"></script>
  16. <script type="text/javascript" src="js/admin_main.js"></script>

  17. <style type="text/css">
  18. //css省略 详细代码见附件
  19. </style>
  20. </head>
  21. <body>
  22. <div id="loading-mask"></div>
  23. <div id="loading">
  24. <div style="text-align: center; padding-top: 25%">
  25. <img src="images/loading32.gif" width="32" height="32"
  26. style="margin-right: 8px;" />
  27. 页面加载中......
  28. </div>
  29. </div>
  30. </body>
  31. </html>

很简单吧 只用loading这个div里面的图片 大家去images里面看看就知道了 页面会不断播放那个gif同时显示"页面加载中..."


直到整个页面加载完毕


[html]  ​​view plain​


  1. <script type="text/javascript" src="js/admin_main.js"></script>

我们再看看admin_main.js

这部分很长很长 大家有点耐心 我先整体讲一下
从12-67行的代码 显示了后台管理部分的代码
从75-188行的代码 显示的是资源共享的代码
至于两部分中的listener部分 暂时先不管 它处理的是导航树被点击后的效果
从196-213行的代码吧上面两部分用tabPanel 集合起来作为一个整体
同时 注意这部分代码region : 'west'  可以知道这个整体又作为一个borderlayout布局的左边部分
从217-223行的代码 显示的是整个页面的顶部
从227-245行的代码 我们可以认为它定义了一个"类"(或者说是界面也行) 它就是整个屏幕的主题
从246-265部分 用的是继承的知识 我们定义了一个新的组件 MainPanel
可参考下面这篇文章
​​​javascript:void(0)​​​mainTabPanel = new MainPanel();
这个很容易理解了 我们的mainTabPanel是MainPanel的一个实例
当然这里也需要一点frame的知识
​http://www.w3school.com.cn/tags/tag_frame.asp​​现在大家回想12-67 75-188 部分的listener 应该能看懂了

[javascript]  ​​view plain​


1. Ext.BLANK_IMAGE_URL = 'ext/resources/images/default/s.gif';
2. Ext.QuickTips.init();
3. var menu = null;
4. var mainTabPanel = null;
5. var rightMenu = null;
6.
7. Ext.onReady(function(){
8.
9. var appUrlData;
10. var appUrlStore;
11.
12. var rightRoot = new Ext.tree.AsyncTreeNode({
13. 'rightRoot',
14. '后台管理rightRoot',
15. true
16. });
17.
18. var rightLoader = new Ext.tree.TreeLoader({
19. 'getAdminAppTree.action'
20. });
21. function(response, node, callback) {
22. var json = response.responseText;
23. try {
24. "(" + json + ")");
25. // 从json中获得json数组,这里的appTree与Struts2返回的json对象中的appTree对应
26. var o = json["jsonText"];
27. "(" + o + ")");
28. if(o==""||o==null){
29. "mainframe").contentWindow.location.href = "common/global_error.jsp";
30. else{
31. node.beginUpdate();
32. for (var i = 0, len = o.length; i < len; i++) {
33. var n = this.createNode(o[i]);
34. if (n) {
35. node.appendChild(n);
36. }
37. }
38. node.endUpdate();
39. if (typeof callback == "function") {
40. this, node);
41. }
42. }
43. catch (e) {
44. this.handleFailure(response);
45. }
46. }
47.
48. new Ext.tree.TreePanel({
49. 'rightMenu',
50. loader : rightLoader,
51. '后台管理rightMenu',
52. root : rightRoot,
53. true,
54. true,
55. true,
56. true,
57. false,
58. /*frame : true,*/
59. listeners: {
60. function(n,e) {
61. if(n.isLeaf()){
62. '<iframe id="mainframe" scrolling="auto" frameborder="0" width="100%" height="100%" src="'+n.attributes.url+'"></iframe>',false);
63. mainTabPanel.setActiveTab(0);
64. }
65. }
66. }
67. });
68.
69.
70. //*******************************************//
71.
72.
73. //资源共享的三个组件 start end在188左右
74. //其一 (其实每一个组将都是一个treePanel)
75. var appTreeRoot1 = new Ext.tree.AsyncTreeNode({
76. 'appTreeRoot1',
77. true
78. });
79. var appTreeLoader1 = new Ext.tree.TreeLoader(
80. 'appTreeLoader1',
81. 'getGroupAppTree.action?appGroupId=1'
82. }
83. );
84. var appTreeMenu1 = new Ext.tree.TreePanel({
85. 'menu1',
86. loader : appTreeLoader1,
87. ' 资源共享appTreeMenu1',
88. root : appTreeRoot1,
89. false,
90. true,//滚动条
91. true,//是否使用箭头样式
92. true,//展开,收缩动画
93. false,
94. /*
95. enableDD : true,
96. frame : true,
97. */
98. listeners: {
99. function(n,e) {
100.
101. '<iframe id="mainframe" scrolling="auto" frameborder="0" width="100%" height="100%" src="'+n.attributes.url+'"></iframe>',false);
102. mainTabPanel.setActiveTab(0);
103. }
104. }
105. });
106.
107. //其二
108. var appTreeRoot2 = new Ext.tree.AsyncTreeNode({
109. 'appTreeRoot2',
110. true
111. });
112. var appTreeLoader2 = new Ext.tree.TreeLoader(
113. 'appTreeLoader2',
114. 'getGroupAppTree.action?appGroupId=2'
115. }
116. );
117. var appTreeMenu2 = new Ext.tree.TreePanel({
118. 'menu2',
119. loader : appTreeLoader2,
120. ' 资源管理appTreeMenu2',
121. root : appTreeRoot2,
122. false,
123. true,//滚动条
124. true,//是否使用箭头样式
125. true,//展开,收缩动画
126. false,
127. /*
128. enableDD : true,
129. frame : true,
130. */
131. listeners: {
132. function(n,e) {
133. '<iframe id="mainframe" scrolling="auto" frameborder="0" width="100%" height="100%" src="'+n.attributes.url+'"></iframe>',false);
134. mainTabPanel.setActiveTab(0);
135. // Ext.getDom("mainframe").contentWindow.location.href =n.attributes.url;
136. }
137. }
138. });
139.
140. //其三
141. var appTreeRoot10 = new Ext.tree.AsyncTreeNode({
142. 'appTreeRoot5',
143. true
144. });
145. var appTreeLoader10 = new Ext.tree.TreeLoader(
146. 'appTreeLoader5',
147. 'getGroupAppTree.action?appGroupId=10'
148. }
149. );
150. var appTreeMenu10 = new Ext.tree.TreePanel({
151. 'menu10',
152. loader : appTreeLoader10,
153. ' 账号管理',
154. root : appTreeRoot10,
155. false,
156. true,//滚动条
157. true,//是否使用箭头样式
158. true,//展开,收缩动画
159. false,
160. /*
161. enableDD : true,
162. frame : true,
163. */
164. listeners: {
165. function(n,e) {
166. '<iframe id="mainframe" scrolling="auto" frameborder="0" width="100%" height="100%" src="'+n.attributes.url+'"></iframe>',false);
167. mainTabPanel.setActiveTab(0);
168.
169. // Ext.getDom("mainframe").contentWindow.location.href =n.attributes.url;
170. }
171. }
172. });
173.
174. var leftAppTreeMenu = new Ext.Panel({
175. 'leftAppTreeMenu',
176. 'accordion',
177. false,
178. '资源共享asdfasdf',
179. layoutConfig:{
180. true,
181. true,
182. false},
183. items:[appTreeMenu1,appTreeMenu2,appTreeMenu10]
184.
185. });
186.
187. // 开始于75资源共享 三个组件 集合起来 使用acordion视图
188.
189.
190. //menu是整个左边导航
191. //注意menu是tabPanel
192. //leftapptreemenu是panel
193. //rightMenu是treemenu 与leftapptreemenu的三个组件是一个类型
194. //在menu之上 还有一个viewport 它作为全局界面 使用borderlayout
195. //menu的region是west
196. new Ext.TabPanel( {
197. 'menu',
198. activeTab : 0,
199. width : 310,
200. true,
201. 'west',
202. // deferredRender : false,
203. true,
204. minTabWidth : 100,
205. tabWidth : 100,
206. true,
207. items : [leftAppTreeMenu,rightMenu],
208. listeners:{
209. function(t, tab) {
210. tab.doLayout();
211. }
212. }
213. });
214.
215.
216.
217. var northpanel = new Ext.Panel({
218. 'north',
219. 'north',
220. 'column',
221. height:100,
222. '<div style="width:100%; background: url(images/main_title_bg.gif) repeat-x;"><img src="images/main_title.gif" /><span id="logout"><a href="javascript:void(0)" οnclick="popHelp()">用户手册</a> | <a href="logout.action" target="_top">注销</a></span></div>'
223. });
224.
225.
226.
227. function() {
228. this.openTab = function(panel, id) {
229. var o = (typeof panel == "string" ? panel : id || panel.id);
230. var tab = this.getComponent(o);
231. if (tab) {
232. this.setActiveTab(tab);
233. else if (typeof panel != "string") {
234. panel.id = o;
235. var p = this.add(panel);
236. this.setActiveTab(p);
237. }
238. };
239. this.closeTab = function(panel, id) {
240. var o = (typeof panel == "string" ? panel : id || panel.id);
241. var tab = this.getComponent(o);
242. if (tab) {
243. this.remove(tab);
244. }
245. };
246. this, {
247. 'main',
248. 'center',
249. '0 5 5 0',
250. true,
251. minTabWidth : 180,
252. tabWidth : 180,
253. true,
254. activeTab : 0,
255. /*draggable : true,*/
256. items : {
257. 'homePage',
258. '主页',
259. false,
260. '<iframe id="mainframe" name="mainframe" scrolling="yes" frameborder="0" width="100%" height="100%" src="common/blank.html"></iframe>'
261. }
262. });
263. };
264.
265. Ext.extend(MainPanel, Ext.TabPanel);
266.
267. new MainPanel();
268.
269.
270. var viewport = new Ext.Viewport({
271. 'border',
272. items : [northpanel,mainTabPanel,menu]
273. });
274.
275.
276. });


这个主面板 最开始的时候引用的src是common/blank.html 白板一张而已

[javascript]
​​view plain​​


1. var viewport = new Ext.Viewport({
2. 'border',
3. items : [northpanel,mainTabPanel,menu]
4. });
ViewPort不必细究 就是一个全屏的window而已

看他的布局 大家就应该明白 这个viewPort就是我们看到的界面


前后台交互用的是json 与struts 这里就不再赘述相关知识点了 网上资料一搜一大堆

下面是响应的action处理方法


[java]
​​view plain​​


1. /**
2. * 读取系统管理员"后台管理"版块的目录树结构
3. */
4. public String getAdminAppTree() throws Exception {
5. "getAdminAppTree");
6. this.jsonText = "[{'id':6,'text':'角色管理','children':[{'id':61,'text':'创建角色','leaf':true,'url':'modules/role/creatRole/creatRole.jsp'},{'id':62,'text':'设定角色应用权限','leaf':true,'url':'modules/role/setRoleApp/setRoleApp.jsp'},{'id':64,'text':'删除角色','leaf':true,'url':'modules/role/deleteRole/deleteRole.jsp'}]},{'id':7,'text':'用户管理','children':[{'id':71,'text':'创建用户','leaf':true,'url':'modules/user/creatUser/creatUser.jsp'},{'id':72,'text':'用户信息管理','leaf':true,'url':'modules/user/viewUserInf/viewUserInf.jsp'},{'id':73,'text':'设定用户所属角色','leaf':true,'url':'modules/user/setUserRole/setUserRole.jsp'}]}]";
7. "jsonText= "+this.jsonText);
8.
9. return SUCCESS;
10. }
11.
12. /**
13. * 根据GroupId,读取该用户在该应用组内的所有应用
14. */
15. public void getGroupAppTree() throws Exception {
16. null;
17. "getGroupAppTree 默认");
18. if (appGroupId==10) {
19. "getGroupAppTree 10");
20. new JSONArray("[{'id':11,'text':'标准化资源共享','leaf':true,'url':'modules/file/baseShare/baseShare.jsp'},{'id':12,'text':'标准化工具','leaf':true,'url':'modules/file/tool/tool.jsp'},{'id':13,'text':'资源环境共享','leaf':true,'url':'modules/file/webShare/webShare.jsp'}]");
21. }
22. if (appGroupId==2) {
23. "getGroupAppTree 2");
24. new JSONArray("[{'id':21,'text':'资源检索','leaf':true,'url':'modules/Manager/search/search.jsp'},{'id':23,'text':'资源审核','leaf':true,'url':'modules/Manager/manager/manager.jsp'},{'id':24,'text':'资源删除','leaf':true,'url':'modules/Manager/delete/delete.jsp'},{'id':27,'text':'资源结算','leaf':true,'url':'modules/Manager/cal/cal.jsp'}]");
25. }
26. if (appGroupId==1) {
27. "getGroupAppTree 1");
28. new JSONArray("[{'id':101,'text':'修改账号信息','leaf':true,'url':'modules/account/changeAccountInf/changeAccountInf.jsp'},{'id':102,'text':'修改账号密码','leaf':true,'url':'modules/account/changePassword/changePassword.jsp'},{'id':104,'text':'权限申请','leaf':true,'url':'modules/account/applyPermission/applyPermission.jsp'}]");
29. }
30.
31.
32. PrintWriter out;
33. this.response.setContentType("text/html;charset=UTF-8");
34. this.response.getWriter();
35. out.print(ja.toString());
36. out.close();
37. }
web.xml,struts.xml这里就不写了 看附件

参考资料


​http://wenku.baidu.com/link?url=NE2POFUVQ4QopprUDiRmgyj3McqpT8WOJ5yw7Rp59GGa56BBm1lB2aEiaZ-anxgghfm4hTYHpF9mMfLXQSgc92dUV-1B7x4qoxcnzG4Zv5u​


​http://www.w3school.com.cn/tags/tag_frame.asp​