之前项目中是使用的最多两级菜单,所以当时写的是两个for 循环,一旦多层菜单,维护起来就麻烦,所以今天使用递归实现导航栏动态生成。在这里主要java 后台代码,以及简单js 递归后台json 数据。数据库就没有在这里设计。
1、Menu实体类
package com.dairuijie.pojo; import java.util.List; /** * 菜单类 * * @Title: Menu.java * @Package com.dairuijie.pojo * @author Drj * @date 2018年3月2日 下午6:15:00 * @version V1.0 */ public class Menu { private String id; // 菜单名称 private String menuName; // 父菜单id private String parentId; // 菜单url private String url; // 菜单图标 private String icon; // 菜单顺序 private int order; // 子菜单 private List<Menu> childMenus; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getMenuName() { return menuName; } public void setMenuName(String menuName) { this.menuName = menuName; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public List<Menu> getChildMenus() { return childMenus; } public void setChildMenus(List<Menu> childMenus) { this.childMenus = childMenus; } }
2、测试递归类
package com.dairuijie.controller; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.dairuijie.pojo.Menu; import com.google.gson.Gson; /** * * @Title: MenuTest.java * @Package com.dairuijie.controller * @author Drj * @date 2018年3月2日 下午7:00:56 * @version V1.0 */ public class MenuTest { private static List<Menu> getChild(String id, List<Menu> rootMenu) { List<Menu> childList = new ArrayList<>();//存放直接子菜单 /** *开始遍历二级菜单以及它的直接子菜单 */ for (Menu menu : rootMenu) { // 遍历所有节点,将父菜单id与传过来的id比较 if (StringUtils.isNotBlank(menu.getParentId())) {//导入org.apache.commons.lang3.StringUtils; if (id.equals(menu.getParentId())) {//尽量让id 在前面,因为他不会为空(数据库设计为主键),parentId 不一定都有值。 childList.add(menu);//相等的话说明这些使它(id)的直接子节点,加入childList } } }//这时候已经将一级菜单以及一级的直接子孩子遍历出来了。 /** * 把子菜单的直接子菜单再循环一遍 * 这时候就是从Menu的直接子菜单中获得需要遍历的菜单也就是childList */ for (Menu menu : childList) { if (StringUtils.isBlank(menu.getUrl())) {//这个判断的意思是 如果url 不为空说明是最后一个节点,为空说明他不是最后一个子节点,这时候就需要去遍历 menu.setChildMenus(getChild(menu.getId(), rootMenu));//递归 } } if (childList.size() == 0) {// 递归退出条件(走到这里childList 大小等于0 说明该节点就是最后一个) return null; } return childList; } public static void main(String[] args) { List<Menu> rootMenus = new ArrayList<Menu>();//假设是从数据库查出来的 List<Menu> menuList = new ArrayList<Menu>(); /** * 先找到所有的一级菜单 */ for (int i = 0; i < rootMenus.size(); i++) { if (StringUtils.isBlank(rootMenus.get(i).getParentId()) || "0".equals(rootMenus.get(i).getParentId())) {// 一级菜单没有parentId (或是等于0,看怎么数据库怎么设置) menuList.add(rootMenus.get(i)); } } /** * 一级菜单之后,开始递归子菜单 */ for (Menu menu : menuList) { menu.setChildMenus(getChild(menu.getId(), rootMenus)); } Map<String,Object> jsonMap = new HashMap<>(); jsonMap.put("menu", menuList); System.out.println(new Gson().toJson(jsonMap));//json 字符串 前端遍历 } }
3、前端递归解析json 数据。
$(function () { var showlist = $("<ul></ul>"); showall(menulist.menulist, showlist); $("#div_menu").append(showlist); }); /** * parent为要组合成html的容器 * menu_list为后台json数据 */ function showall(menu_list, parent) { for (var menu in menu_list) { //如果有子节点,则遍历该子节点 if (menu_list[menu].menulist.length > 0) { //创建一个子节点li var li = $("<li></li>"); //将li的文本设置好,并马上添加一个空白的ul子节点,并且将这个li添加到父亲节点中 $(li).append(menu_list[menu].MName).append("<ul></ul>").appendTo(parent); //将空白的ul作为下一个递归遍历的父亲节点传入 showall(menu_list[menu].menulist, $(li).children().eq(0)); } //如果该节点没有子节点,则直接将该节点li以及文本创建好直接添加到父亲节点中 else { $("<li></li>").append(menu_list[menu].MName).appendTo(parent); } } }