尚硅谷尚筹网单一架构知识十五树形菜单

1 建模

1.1 创建数据库表

CREATE TABLE t_menu (
id INT (11) NOT NULL auto_increment,
pid INT (11),
name VARCHAR (200),
url VARCHAR (200),
icon VARCHAR (200),
PRIMARY KEY (id)
);
1.2创建实体类
成的Menu实体类需要做一些修改


// 对应数据库表主键
private Integer id;

// 对应父节点id(如果pid为null,则说明当前节点是根节点)
private Integer pid;

// 节点名称
private String name;

// 节点对应的URL地址
private String url;

// 节点的图标
private String icon;

// 当前节点的子节点集合,设置默认值是为了避免组装节点时空指针异常
private List<Menu> children = new ArrayList<>();

// 控制节点展开还是折叠,设置为true是让整个树形菜单默认展开
private Boolean open = true;

2 在页面显示树形结构

2.1 后端操作
把树形结构组装好,具体来说是:给前端返回根节点对象。在根节点中包含子节点,子节点中再包含下一级的子节点。

@RequestMapping("/menu/get/whole/tree")
public ResultEntity<Menu> getWholeTree() {
	
	// 1.查询所有的树形节点用于组装
	List<Menu> menuList = menuService.getAll();
	
	// 2.将List<Menu>转换为Map<Menu的id,Menu>
	Map<Integer,Menu> menuMap = new HashMap<>();
	
	for (Menu menu : menuList) {
		Integer id = menu.getId();
		menuMap.put(id, menu);
	}
	
	// 3.声明变量用于存储根节点对象
	Menu rootNode = null;
	
	// 4.遍历List<Menu>
	for (Menu menu : menuList) {
		
		// 5.获取当前Menu对象的pid属性
		Integer pid = menu.getPid();
		
		// 6.判断pid是否为null
		if(pid == null) {
			
			// 7.如果pid为null,说明当前节点是根节点,所以赋值
			rootNode = menu;
			
			// 8.根节点没有父节点,所以不必找父节点组装,本次for循环停止执行,继续执行下一次循环
			continue ;
		}
		
		// 9.既然pid不为null,那么我们根据这个pid查找当前节点的父节点。
		Menu father = menuMap.get(pid);
		
		// 10.组装:将menu添加到maybeFather的子节点集合中
		father.getChildren().add(menu);
	}
	
	return ResultEntity.successWithData(rootNode);
}

2.2 前端操作

2.2.1 创建menu-page.jsp


主体内容如下:

权限菜单列表
    **2.2.2 加入zTree环境**

    ztree
    2.2.3 显示树形结构

    function initWholeTree() {
    	// setting对象中包含zTree的设置属性
    	var setting = {
    		"view": {
    			"addDiyDom": showMyIcon,
    			"addHoverDom": addHoverDom,
    			"removeHoverDom": removeHoverDom
    		},
    		"data": {
    			"key": {
    				"url": "notExistsProperty" // 阻止点击节点后跳转
    			}
    		}
    	};
    
    	// 发送Ajax请求获取zNodes数据
    	$.ajax({
    		"url":"menu/get/whole/tree.json",
    		"type":"post",
    		"dataType":"json",
    		"success":function(response){
    			
    			var result = response.result;
    			
    			if(result == "SUCCESS") {
    				// 用于显示树形结构的节点数据
    				var zNodes = response.data;
    				
    		
    				// 执行树形结构的初始操作
    				$.fn.zTree.init($("#treeDemo"), setting, zNodes);
    			}
    			
    			if(result == "FAILED") {
    				layer.msg("加载菜单数据失败!原因是:"+response.message);
    			}
    		},
    		"error":function(response){
    			layer.msg("加载菜单数据失败!原因是:"+response.message);
    		}
    	});
    }
    

    2.2.4 声明函数将图标修改为自定义图标

    // 由setting.view.addDiyDom属性引用,负责显示自定义图标
    // treeId是<ul id="treeDemo" class="ztree"></ul>的id属性值
    // treeNode对应每一个树形节点
    function showMyIcon(treeId, treeNode) {
    	
    	// 获取当前节点的id
    	var currentNodeId = treeNode.tId;
    	
    	// 获取新的class值用于替换
    	var newClass = treeNode.icon;
    	
    	// 在当前节点id之后附加“_ico”得到目标span的id
    	var targetSpanId = currentNodeId + "_ico";
    	
    	// 将目标span的旧class移除,添加新class
    	$("#"+targetSpanId)
    		.removeClass()
    		.addClass(newClass)
    		.css("background","");
    }
    
    

    附:节点图标修改前后HTML代码变化



    2.2.5 节点结构
    在这里插入图片描述

    id结构:treeDemo_节点序号_节点具体部件
    2.2.6 阻止点击节点后跳转
    使用了setting.data.key.url属性
    在这里插入图片描述

    3 生成按钮组

    3.1 按钮组生成规则
    3.1.1 根节点(level 0)
    增加子节点
    3.1.2 level为1的有子节点的节点
    增加子节点
    修改
    3.1.3 level为1的无子节点的节点
    增加子节点
    删除
    修改
    3.1.4 level为2的节点
    删除
    修改
    3.2 设计按钮组所在span的id
    规则:treeDemo_序号_btnGrp
    举例:treeDemo_20_btnGrp
    3.3 各个按钮HTML标签


      


      


      


    3.4 声明函数生成按钮组

    // 专门生成按钮组的函数
    function generateBtnGrp(treeNode) {
    	
    	// 获取当前节点的id(HTML中li标签的id)
    	var treeNodeId = treeNode.tId;
    	
    	// 获取当前节点在数据库中的id值
    	// Menu实体类中的属性,都可以通过treeNode以“.属性名”的方式直接访问
    	var menuId = treeNode.id;
    	
    	// 组装按钮组所在的span的id
    	var btnGrpSpanId = treeNodeId + "_btnGrp";
    	
    	// 生成span标签对应的jQuery对象
    	var $span = $("<span id='"+btnGrpSpanId+"'></span>");
    	
    	// 获取当前节点的level值
    	var level = treeNode.level;
    	
    	// 声明三种按钮
    	var addBtn = "<a οnclick='showAddModal(this)' id='"+menuId+"' class='btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' title='添加子节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-plus rbg'></i></a>";
    	var editBtn = "<a οnclick='showEditModal(this)' id='"+menuId+"' class='btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' title='编辑节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-edit rbg'></i></a>";
    	var removeBtn = "<a οnclick='showConfirmModal(this)' id='"+menuId+"' class='btn btn-info dropdown-toggle btn-xs' style='margin-left:10px;padding-top:0px;' title='删除节点'>&nbsp;&nbsp;<i class='fa fa-fw fa-times rbg'></i></a>";
    	
    	// 根据level进行判断
    	if(level == 0) {
    		$span.append(addBtn);
    	}
    	
    	if(level == 1) {
    		
    		if(treeNode.children.length > 0) {
    			
    			$span.append(addBtn+" "+editBtn);
    			
    		} else {
    			
    			$span.append(addBtn+" "+editBtn+" "+removeBtn);
    			
    		}
    		
    	}
    	
    	if(level == 2) {
    		
    		$span.append(editBtn+" "+removeBtn);
    		
    	}
    	
    	return $span;
    }
    
    

    3.5 addHoverDom(treeId, treeNode)函数

    // 在鼠标移入节点范围时添加自定义控件
    function addHoverDom(treeId, treeNode) {
    	
    	// 在执行添加前,先进行判断,如果已经添加过,就停止执行
    	// 组装按钮组所在的span标签的id
    	var btnGrpSpanId = treeNode.tId + "_btnGrp";
    	
    	var btnGrpSpanLength = $("#"+btnGrpSpanId).length;
    	
    	if(btnGrpSpanLength > 0) {
    		return ;
    	}
    	
    	// 由于按钮组是放在当前节点中的超链接(a标签)后面,所以先定位到a标签
    	// 按id生成规则组装a标签的id
    	var anchorId = treeNode.tId + "_a";
    	
    	// 调用已封装函数生成按钮组
    	var $btnGrpSpan = generateBtnGrp(treeNode);
    	
    	// 在a标签后面追加按钮组
    	$("#"+anchorId).after($btnGrpSpan);
    	
    }
    
    
    

    3.6 removeHoverDom(treeId, treeNode)函数

    // 在鼠标移出节点范围时删除自定义控件
    function removeHoverDom(treeId, treeNode) {
    	
    	// 组装按钮组所在的span标签的id
    	var btnGrpSpanId = treeNode.tId + "_btnGrp";
    	
    	// 删除对应的元素
    	$("#"+btnGrpSpanId).remove();
    }
    
    

    在这里插入图片描述

    • 0
      点赞
    • 1
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值