有時候, 我們需要用到菜單列表,但是怎么樣去實現一個菜單列表的編寫呢,這是一重要的問題。
比如我們需要編寫一個樹形結構的菜單,那么我們可以使用JQuery的zTree插件:http://www.treejs.cn/v3/main.php#_zTreeInfo
例如現在需要編寫一個這樣的菜單列表。那么就可以使用JQuery的zTree插件。
先看一下數據庫表結構。
CREATE TABLE `permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`pid` int(11) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
1、前端頁面。
<div class="panel-body"> <ul id="permissionTree" class="ztree"></ul> </div>
<script> $(function () { var setting = { async: { enable: true, url:"${APP_PATH}/permission/loadData", autoParam:["id", "name=n", "level=lv"], otherParam:{"otherParam":"zTreeAsyncTest"}, } }; //樹形結構 $.fn.zTree.init($("#permissionTree"), setting); }); </script>
2、在這里呢,我使用的是ssm框架。所以就提交到controller層來進行操作。
Permission類的代碼
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class Permission { 5 6 private Integer id; 7 private String name; 8 private String url; 9 private Integer pid; 10 private boolean open = true; 11 private boolean checked = false; 12 private String icon; 13 private List<Permission> children = new ArrayList<Permission>(); 14 15 public boolean isChecked() { 16 return checked; 17 } 18 public void setChecked(boolean checked) { 19 this.checked = checked; 20 } 21 public String getIcon() { 22 return icon; 23 } 24 public void setIcon(String icon) { 25 this.icon = icon; 26 } 27 public Integer getId() { 28 return id; 29 } 30 public void setId(Integer id) { 31 this.id = id; 32 } 33 public String getName() { 34 return name; 35 } 36 public void setName(String name) { 37 this.name = name; 38 } 39 public String getUrl() { 40 return url; 41 } 42 public void setUrl(String url) { 43 this.url = url; 44 } 45 public Integer getPid() { 46 return pid; 47 } 48 public void setPid(Integer pid) { 49 this.pid = pid; 50 } 51 public boolean isOpen() { 52 return open; 53 } 54 public void setOpen(boolean open) { 55 this.open = open; 56 } 57 public List<Permission> getChildren() { 58 return children; 59 } 60 public void setChildren(List<Permission> children) { 61 this.children = children; 62 } 63 64 }
使用controller這里我使用三種方式來進行查找 。
(1)遞歸方式讀取各節點
controller層
/** * 異步加載樹結點 * @return */ @RequestMapping("/loadData") @ResponseBody public List<Permission> loadData(){ // 遞歸查詢數據 Permission parent = new Permission(); parent.setId(0); queryChildPermissions(parent); return parent.getChildren(); } /** * 遞歸查詢許可信息 * 1) 方法自己調用自己 * 2)方法一定要存在跳出邏輯 * 3)方法調用時,參數之間應該有規律 * 4) 遞歸算法,效率比較低 * @param parent */ private void queryChildPermissions(Permission parent){ List<Permission> childPermissions = permissionService.queryChildPermissions(parent.getId()); for (Permission permission :childPermissions) { queryChildPermissions(permission); } parent.setChildren(childPermissions); }
service層
public Permission queryRootPermission() { return permissionMapper.queryRootPermission(); }
mappern層
@Select("select * from permission where pid is null")
Permission queryRootPermission();
(2)嵌套for循環方式讀取各節點
controller層
1 /** 2 * 異步加載樹結點 3 * @return 4 */ 5 @RequestMapping("/loadData") 6 @ResponseBody 7 public List<Permission> loadData(){ 8 List<Permission> permissions=new ArrayList<Permission>(); 9 // 查詢所有的許可數據 10 List<Permission> ps = permissionService.queryAll(); 11 for ( Permission p : ps ) { 12 // 子節點 13 Permission child = p; 14 if ( p.getPid() == 0 ) { 15 permissions.add(p); 16 } else { 17 for ( Permission innerPermission : ps ) { 18 if ( child.getPid().equals(innerPermission.getId()) ) { 19 // 父節點 20 Permission parent = innerPermission; 21 // 組合父子節點的關系 22 parent.getChildren().add(child); 23 break; 24 } 25 } 26 } 27 } 28 29 30 return permissions; 31 }
service層
public List<Permission> queryAll() { return permissionMapper.queryAll(); }
mapper層
@Select("select * from permission")
List<Permission> queryAll();
(3)map集合方式讀取各節點
controller層
/** * 異步加載樹結點 * @return */ @RequestMapping("/loadData") @ResponseBody public List<Permission> loadData(){ List<Permission> permissions=new ArrayList<Permission>(); // 查詢所有的許可數據 List<Permission> ps = permissionService.queryAll(); Map<Integer, Permission> permissionMap = new HashMap<Integer, Permission>(); for (Permission p : ps) { permissionMap.put(p.getId(), p); } for ( Permission p : ps ) { Permission child = p; if ( child.getPid() == 0 ) { permissions.add(p); } else { Permission parent = permissionMap.get(child.getPid()); parent.getChildren().add(child); } } return permissions; }
service層
public List<Permission> queryAll() { return permissionMapper.queryAll(); }
mapper層
@Select("select * from permission")
List<Permission> queryAll();
三種方法的總結 :
使用遞歸會使數據庫查詢非常頻繁,不能進行性能優化
使用嵌套for循環沒有使用索引,不夠快速
使用map集合就使用了索引,加快查詢速度。