




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
利用多叉树实现Ext JS中的无限级树形菜单利用多叉树实现Ext JS中的无限级树形菜单(一种构建多级有序树形结构JSON的方法) 一、问题研究的背景和意义 目前在Web应用程序开发领域,Ext JS框架已经逐渐被广泛使用,它是富客户端开发中出类拔萃的框架之一。在Ext的UI控件中,树形控件无疑是最为常用的控件之一,它用来实现树形结构的菜单。TreeNode用来实现静态的树形菜单,AsyncTreeNode用来实现动态的异步加载树形菜单,后者最为常用,它通过接收服务器端返回来的JSON格式的数据,动态生成树形菜单节点。动态生成树有两种思路:一种是一次性生成全部树节点,另一种是逐级加载树节点(利用AJAX,每次点击节点时查询下一级节点)。对于大数据量的菜单节点来说,逐级加载是比较合适的选择,但是对于小数据量的菜单来说,一次性生成全部节点应该是最为合理的方案。在实际应用开发中,一般不会遇到特别大数据量的场景,所以一次性生成全部菜单节点是我们重点研究的技术点,本文就是介绍基于Ext JS的应用系统中如何将数据库中的无限级层次数据一次性在界面中生成全部菜单节点(例如在界面中以树形方式一次性展示出银行所有分支机构的信息),同时对每一个层次的菜单节点按照某一属性和规则排序,展示出有序的菜单树。 解决Ext JS无限级树形菜单的问题,可以拓展出更多的应用场景,例如树形结构表格TreeGrid,一次性生成树形表格,对树形表格进行完整分页,对表格列进行全排序;或者可以利用本文的思路扩展出其他的更复杂的应用场景。 先看两个图例,有个直观上的认识:图一,银行分支机构树形结构菜单 图二,树形结构表格 二、详细设计方案 让我们先看一段代码片段: 文件一,branchTree.html (Ext树形控件页面) Js代码 1.Ext.onReady( 2. function() 3. var tree = new Ext.tree.TreePanel( 4. height: 300, 5. width: 400, 6. animate:true, 7. enableDD:true, 8. containerScroll: true, 9. rootVisible: false, 10. frame: true, 11. / getBranch.do请求服务器返回多级树形结构的JSON字符串 12. loader: new Ext.tree.TreeLoader(dataUrl:getBranch.do), 13. root : new Ext.tree.AsyncTreeNode(id:0,text:根结点) 14. ); 15. tree.expandAll(); 16. 17.); 文件二,branchTreeJSON.jsp (接收getBranch.do请求,返回无限级JSON字符串) Java代码 1. 7. 8. 9. 以上两个程序文件是一次性生成无限级树形菜单所必须的,其中最为关键的部分就是如何生成一个无限级的JSON字符串,返回给客户端的Ext树形控件。对于银行分支机构来说,需要返回类似如下的JSON串: Js代码 1. 2. id: 100000, 3. text: 廊坊银行总行, 4. children: 5. 6. id: 110000, 7. text: 廊坊分行, 8. children: 9. 10. id: 113000, 11. text: 廊坊银行开发区支行, 12. leaf: true 13. , 14. 15. id: 112000, 16. text: 廊坊银行解放道支行, 17. children: 18. 19. id: 112200, 20. text: 廊坊银行三大街支行, 21. leaf: true 22. , 23. 24. id: 112100, 25. text: 廊坊银行广阳道支行, 26. leaf: true 27. 28. 29. , 30. 31. id: 111000, 32. text: 廊坊银行金光道支行, 33. leaf: true 34. 35. 36. 37. 38. 同时还可能需要对树中每一个层次的节点按照某一属性(比如分支机构编号)进行排序,以展示出有序的树形菜单。 现在可以把问题概括为: 1、 把数据库中的层次数据转换成JSON格式的字符串 2、 对树中每一个层次的节点按照某一属性(比如分支机构编号)进行排序 下面介绍解决问题的思路: 在数据结构这门课中,我们都学过树,无限级树形菜单就可以抽象成一种多叉树结构,即每个节点下包含多个子节点的树形结构,首先就需要把数据库中的层次数据转换成多叉树结构的对象树,也就是构造出一棵多叉树。 有了数据结构,还要实现相应的算法,我们需要实现两种算法:1、兄弟节点横向排序算法,对隶属于同一个父节点下面的所有直接子节点按照某一节点属性和规则进行排序,保持兄弟节点横向有序;2、先序遍历算法,递归打印出无限级JSON字符串。 概括起来分为三步:1、 构造无序的多叉树结构2、 实现兄弟节点横向排序方法3、 实现先序遍历方法,打印出JSON字符串 如图所示: 三、源代码实现(Java语言版) 实现这样一颗树,需要设计三个类:树类(MultipleTree.java)、节点类(Node.java)、孩子列表类(Children.java);为了方便演示,还需要构造一些假的层次数据,因此还需要建一个构造假数据的类(VirtualDataGenerator.java),以下代码拷贝出来之后可直接运行测试: Java代码 1.package test; 2. 3.import java.util.ArrayList; 4.import java.util.Comparator; 5.import java.util.HashMap; 6.import java.util.Iterator; 7.import java.util.List; 8.import java.util.Map; 9.import java.util.Set; 10.import java.util.Collections; 11. 12./* 13. * 多叉树类 14.*/ 15.public class MultipleTree 16. public static void main(String args) 17. / 读取层次数据结果集列表 18. List dataList = VirtualDataGenerator.getVirtualResult(); 19. 20. / 节点列表(散列表,用于临时存储节点对象) 21. HashMap nodeList = new HashMap(); 22. / 根节点 23. Node root = null; 24. / 根据结果集构造节点列表(存入散列表) 25. for (Iterator it = dataList.iterator(); it.hasNext();) 26. Map dataRecord = (Map) it.next(); 27. Node node = new Node(); 28. node.id = (String) dataRecord.get(id); 29. node.text = (String) dataRecord.get(text); 30. node.parentId = (String) dataRecord.get(parentId); 31. nodeList.put(node.id, node); 32. 33. / 构造无序的多叉树 34. Set entrySet = nodeList.entrySet(); 35. for (Iterator it = entrySet.iterator(); it.hasNext();) 36. Node node = (Node) (Map.Entry) it.next().getValue(); 37. if (node.parentId = null | node.parentId.equals() 38. root = node; 39. else 40. (Node) nodeList.get(node.parentId).addChild(node); 41. 42. 43. / 输出无序的树形菜单的JSON字符串 44. System.out.println(root.toString(); 45. / 对多叉树进行横向排序 46. root.sortChildren(); 47. / 输出有序的树形菜单的JSON字符串 48. System.out.println(root.toString(); 49. 50. / 程序输出结果如下(无序的树形菜单)(格式化后的结果): 51. / 52. / id : 100000, 53. / text : 廊坊银行总行, 54. / children : 55. / 56. / id : 110000, 57. / text : 廊坊分行, 58. / children : 59. / 60. / id : 113000, 61. / text : 廊坊银行开发区支行, 62. / leaf : true 63. / , 64. / 65. / id : 111000, 66. / text : 廊坊银行金光道支行, 67. / leaf : true 68. / , 69. / 70. / id : 112000, 71. / text : 廊坊银行解放道支行, 72. / children : 73. / 74. / id : 112200, 75. / text : 廊坊银行三大街支行, 76. / leaf : true 77. / , 78. / 79. / id : 112100, 80. / text : 廊坊银行广阳道支行, 81. / leaf : true 82. / 83. / 84. / 85. / 86. / 87. / 88. / 89. 90. / 程序输出结果如下(有序的树形菜单)(格式化后的结果): 91. / 92. / id : 100000, 93. / text : 廊坊银行总行, 94. / children : 95. / 96. / id : 110000, 97. / text : 廊坊分行, 98. / children : 99. / 100. / id : 111000, 101. / text : 廊坊银行金光道支行, 102. / leaf : true 103. / , 104. / 105. / id : 112000, 106. / text : 廊坊银行解放道支行, 107. / children : 108. / 109. / id : 112100, 110. / text : 廊坊银行广阳道支行, 111. / leaf : true 112. / , 113. / 114. / id : 112200, 115. / text : 廊坊银行三大街支行, 116. / leaf : true 117. / 118. / 119. / , 120. / 121. / id : 113000, 122. / text : 廊坊银行开发区支行, 123. / leaf : true 124. / 125. / 126. / 127. / 128. / 129. 130. 131. 132. 133. 134. 135./* 136.* 节点类 137.*/ 138.class Node 139. /* 140. * 节点编号 141. */ 142. public String id; 143. /* 144. * 节点内容 145. */ 146. public String text; 147. /* 148. * 父节点编号 149. */ 150. public String parentId; 151. /* 152. * 孩子节点列表 153. */ 154. private Children children = new Children(); 155. 156. / 先序遍历,拼接JSON字符串 157. public String toString() 158. String result = 159. + id : + id + 160. + , text : + text + ; 161. 162. if (children != null & children.getSize() != 0) 163. result += , children : + children.toString(); 164. else 165. result += , leaf : true; 166. 167. 168. return result + ; 169. 170. 171. / 兄弟节点横向排序 172. public void sortChildren() 173. if (children != null & children.getSize() != 0) 174. children.sortChildren(); 175. 176. 177. 178. / 添加孩子节点 179. public void addChild(Node node) 180. this.children.addChild(node); 181. 182. 183. 184./* 185.* 孩子列表类 186.*/ 187.class Children 188. private List list = new ArrayList(); 189. 190. public int getSize() 191. return list.size(); 192. 193. 194. public void addChild(Node node) 195. list.add(node); 196. 197. 198. / 拼接孩子节点的JSON字符串 199. public String toString() 200. String result = ; 201. for (Iterator it = list.iterator(); it.hasNext();) 202. result += (Node) it.next().toString(); 203. result += ,; 204. 205. result = result.substring(0, result.length() - 1); 206. result += ; 207. return result; 208. 209. 210. / 孩子节点排序 211. public void sortChildren() 212. / 对本层节点进行排序 213. / 可根据不同的排序属性,传入不同的比较器,这里传入ID比较器 214. Collections.sort(list, new NodeIDComparator(); 215. / 对每个节点的下一层节点进行排序 216. for (Iterator it = list.iterator(); it.hasNext();) 217. (Node) it.next().sortChildren(); 218. 219. 220. 221. 222./* 223. * 节点比较器 224. */ 225.class NodeIDComparator implements Comparator 226. / 按照节点编号比较 227. public int compare(Object o1, Object o2) 228. int j1 = Integer.parseInt(Node)o1).id); 229. int j2 = Integer.parseInt(Node)o2).id); 230. return (j1 j2 ? -1 : (j1 = j2 ? 0 : 1); 231. 232. 233. 234./* 235. * 构造虚拟的层次数据 236. */ 237.class VirtualDataGenerator 238. / 构造无序的结果集列表,实际应用中,该数据应该从数据库中查询获得; 239. public static List getVirtualResult() 240. List dataList = new ArrayList(); 241. 242. HashMap dataRecord1 = new HashMap(); 243. dataRecord1.put(id, 112000); 244. dataRecord1.put(text, 廊坊银行解放道支行); 245. dataRecord1.put(parentId, 110000); 246. 247. HashMap dataRecord2 = new HashMap(); 248. dataRecord2.put(id, 112200); 249. dataRecord2.put(text, 廊坊银行三大街支行); 250. dataRecord2.put(parentId, 112000); 251. 252. HashMap dataRecord3 = new HashMap(); 253. dataRecord3.put(id, 112100); 254. dataRecord3.put(text, 廊坊银行广阳道支行); 255. dataRecord3.put(parentId, 112000); 256. 257. HashMap dataRecord4 = new HashMap(); 258. dataRecord4.put(id, 113000); 259. dataRecord4.put(text, 廊坊银行开发区支行); 260. dataRecord4.put(parentId, 110000); 261. 262. HashMap dataRecord5 = new HashMap(); 263. dataRecord5.put(id, 100000); 264. dataRecord5.put(text, 廊坊银行总行); 265. dataRecord5.put(parentId, ); 266. 267. HashMap dataRecord6 = new HashMap(); 268. dataRecord6.put(id, 110000); 269. dataRecord6.put(text, 廊坊分行); 270. dataRecord6.put(parentId, 100000); 271. 272. HashMap dataRecord7 = new HashMap(); 273. dataRecord7.put(id, 111000); 274. dataRecord7.put(text, 廊坊银行金光道支行); 275. dataRecord7.put(parentId, 110000); 276. 277. dataList.add(dataRecord1); 278. dataList.add(dataRecord2); 279. dataList.add(dataRecord3); 280. dataList.add(dataRecord4); 281. dataList.add(dataRecord5); 282. dataList.add(dataRecord6); 283. dataList.add(dataRecord7); 284. 285. return dataList; 286. 287. 好了,通过上面的代码,就可以实现多叉树的兄弟节点横向排序和先序遍历了,实现了将层次数据转换为有序无限级JSON字符串的目的。 在实际的项目中,可以把上面的有效代码融入其中,或者在此基础上进行一些扩展: 1、 实现对指定层次的排序(例如只排序第一层的节点,或者只排序某一父节点下的所有子节点)2、 遍历输出树形结构时可以加入判断条件过滤掉某些节点3、 实现节点的删除功能4、 在节点类中增加一个父节点的引用,就可以计算出某一节点所处的级别5、 在不支持层次查询的数据库应用系统中使用该算法实现相同的效果 四、思考与总结 这篇文章的重点是如何构造有序的无限级的树形结构JSON字符串,一次性生成树形菜单,而不是利用AJAX的方式,反复向服务器端发送请求,一级接一级的加载树节点。 既然可以构造无限级的JSON字符串,那么也可以根据这个思路构造无限级的XML字符串,或者构造具有层次结构的UL LI组合(用UL - LI来展示树形结构),或者构造具有层次结构的TABLE(用TABLE来展示树形结构)。如下所示: (1)XML层次结构 Xml
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年跨区域金融资产交易平台风险控制保证金合同
- 2025音乐节巡演演出合同书-梦幻现场版
- 2025年智能化车间设备租赁及运营管理服务合同
- 2025年新型医疗器械引进及推广居间服务合同
- 2025年国际学术论文版权授权与出版合作协议
- 2025新型医疗器械代理引进及全面售后服务合作协议
- 2025年珠宝首饰行业专利技术合作开发与授权合同
- 普通货运公司合同付款管理办法
- 2025输血培训试题及答案
- 建筑装饰绿色环保设计方案
- 内镜床旁预处理培训
- 人文与社会《家乡的山水》黑龙江省地方教材
- 宫内感染的早期识别与诊断专家共识
- 2024儿童营养保健科试题及答案
- 电力系统绝缘保护 过电压防护 电力系统内部过电压及防护
- 行政事业单位法律风险
- 《保障农民工工资支付条例》宣传册
- GB/Z 43427-2023优质服务设计高品质服务以实现极致顾客体验
- 2023年贵州六盘水市盘州市考调事业单位人员60人笔试参考题库(共500题)答案详解版
- 供热管道水压试验操作规范
- GB 5009.227-2023食品安全国家标准食品中过氧化值的测定
评论
0/150
提交评论