从表中可以分析出这是一个三级菜单,‘权限管理’是父节点,‘书籍管理’,‘订单管理’是二级节点,其他的是三级节点
我们可以把分好的二级节点和三级节点加到父节点里
下面也会向大家详细讲解实现左侧菜单的实现步骤
1.实体--Permission
package com.ctb.entity; /** * 菜单权限实体类 * * @author biao * * 2023年7月12日 */ public class Permission { private long id; private String name; private String description; private String url; private long pid; private int ismenu;//控制当前系统的权限是菜单还是按钮 private long displayno;//菜单排序字段 public Permission() { // TODO Auto-generated constructor stub } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public long getPid() { return pid; } public void setPid(long pid) { this.pid = pid; } public int getIsmenu() { return ismenu; } public void setIsmenu(int ismenu) { this.ismenu = ismenu; } public long getDisplayno() { return displayno; } public void setDisplayno(long displayno) { this.displayno = displayno; } public Permission(long id, String name, String description, String url, long pid, int ismenu, long displayno) { super(); this.id = id; this.name = name; this.description = description; this.url = url; this.pid = pid; this.ismenu = ismenu; this.displayno = displayno; } @Override public String toString() { return "Permission [id=" + id + ", name=" + name + ", description=" + description + ", url=" + url + ", pid=" + pid + ", ismenu=" + ismenu + ", displayno=" + displayno + "]"; } }
2.工具类--TreeVo,BuildTree
TreeVo
package com.zking.util; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 权限工具类 * * @author biao * * 2023年7月12日 */ public class TreeVo<T> { /** * 节点ID */ private String id; /** * 显示节点文本 */ private String text; /** * 节点状态,open closed */ private Map<String, Object> state; /** * 节点是否被选中 true false */ private boolean checked = false; /** * 节点属性 */ private Map<String, Object> attributes; /** * 节点的子节点 */ private List<TreeVo<T>> children = new ArrayList<TreeVo<T>>(); /** * 父ID */ private String parentId; /** * 是否有父节点 */ private boolean hasParent = false; /** * 是否有子节点 */ private boolean hasChildren = false; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Map<String, Object> getState() { return state; } public void setState(Map<String, Object> state) { this.state = state; } public boolean isChecked() { return checked; } public void setChecked(boolean checked) { this.checked = checked; } public Map<String, Object> getAttributes() { return attributes; } public void setAttributes(Map<String, Object> attributes) { this.attributes = attributes; } public List<TreeVo<T>> getChildren() { return children; } public void setChildren(List<TreeVo<T>> children) { this.children = children; } public boolean isHasParent() { return hasParent; } public void setHasParent(boolean isParent) { this.hasParent = isParent; } public boolean isHasChildren() { return hasChildren; } public void setChildren(boolean isChildren) { this.hasChildren = isChildren; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public TreeVo(String id, String text, Map<String, Object> state, boolean checked, Map<String, Object> attributes, List<TreeVo<T>> children, boolean isParent, boolean isChildren, String parentID) { super(); this.id = id; this.text = text; this.state = state; this.checked = checked; this.attributes = attributes; this.children = children; this.hasParent = isParent; this.hasChildren = isChildren; this.parentId = parentID; } public TreeVo() { super(); } }
BuildTree
package com.zking.util; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 权限工具类 * * @author biao * * 2023年7月12日 */ public class TreeVo<T> { /** * 节点ID */ private String id; /** * 显示节点文本 */ private String text; /** * 节点状态,open closed */ private Map<String, Object> state; /** * 节点是否被选中 true false */ private boolean checked = false; /** * 节点属性 */ private Map<String, Object> attributes; /** * 节点的子节点 */ private List<TreeVo<T>> children = new ArrayList<TreeVo<T>>(); /** * 父ID */ private String parentId; /** * 是否有父节点 */ private boolean hasParent = false; /** * 是否有子节点 */ private boolean hasChildren = false; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Map<String, Object> getState() { return state; } public void setState(Map<String, Object> state) { this.state = state; } public boolean isChecked() { return checked; } public void setChecked(boolean checked) { this.checked = checked; } public Map<String, Object> getAttributes() { return attributes; } public void setAttributes(Map<String, Object> attributes) { this.attributes = attributes; } public List<TreeVo<T>> getChildren() { return children; } public void setChildren(List<TreeVo<T>> children) { this.children = children; } public boolean isHasParent() { return hasParent; } public void setHasParent(boolean isParent) { this.hasParent = isParent; } public boolean isHasChildren() { return hasChildren; } public void setChildren(boolean isChildren) { this.hasChildren = isChildren; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public TreeVo(String id, String text, Map<String, Object> state, boolean checked, Map<String, Object> attributes, List<TreeVo<T>> children, boolean isParent, boolean isChildren, String parentID) { super(); this.id = id; this.text = text; this.state = state; this.checked = checked; this.attributes = attributes; this.children = children; this.hasParent = isParent; this.hasChildren = isChildren; this.parentId = parentID; } public TreeVo() { super(); } }
3.PermissionDao
package com.ctb.dao; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.ctb.entity.Permission; import com.fasterxml.jackson.databind.ObjectMapper; import com.zking.util.BaseDao; import com.zking.util.BuildTree; import com.zking.util.PageBean; import com.zking.util.TreeVo; public class PermissionDao extends BaseDao<Permission>{ //查询 public List<Permission> list(Permission permission, PageBean pageBean) throws Exception { String sql="select * from t_easyui_permission"; return super.executeQuery(sql, Permission.class, pageBean); } //将平级数据转成有父子关系的数据 // public List<TreeVo<Permission>> menus(Permission permission, PageBean pageBean) throws Exception { // List<TreeVo<Permission>> lst=new ArrayList<TreeVo<Permission>>(); // List<Permission> list = this.list(permission, pageBean); // for (Permission p : list) { // TreeVo<Permission> treevo=new TreeVo<Permission>(); // treevo.setId(p.getId()+""); // treevo.setText(p.getName()); // treevo.setParentId(p.getPid()+""); // lst.add(treevo); // } // return BuildTree.buildList(lst, "0"); // // } //分好的二级节点和三级节点 public List<TreeVo<Permission>> menus(Permission permission, PageBean pageBean) throws Exception { List<TreeVo<Permission>> trees = new ArrayList<TreeVo<Permission>>(); List<Permission> list = this.list(permission, pageBean); for (Permission p : list) { TreeVo<Permission> vo = new TreeVo<>(); vo.setId(p.getId()+""); vo.setText(p.getName());//节点名称 vo.setParentId(p.getPid()+""); trees.add(vo); } return BuildTree.buildList(trees,"0"); } public TreeVo<Permission> menu(Permission permission,PageBean pageBean) throws Exception { List<TreeVo<Permission>> trees = new ArrayList<TreeVo<Permission>>(); List<Permission> list = this.list(permission, pageBean); for (Permission p : list) { TreeVo<Permission> vo = new TreeVo<>(); vo.setId(p.getId()+""); vo.setText(p.getName());//节点名称 vo.setParentId(p.getPid()+""); vo.setChildren(menus(null, null));//将分好的二级节点和三级节点加到顶级节点里 trees.add(vo); } return BuildTree.build(trees); } public static void main(String[] args) throws Exception { List<TreeVo<Permission>> menus = new PermissionDao().menus(null, null); ObjectMapper om = new ObjectMapper(); System.out.println(om.writeValueAsString(menus)); } }
测试直接查询的结果---平级数据
因此我们需借助上面的两个工具类将平级数据转成有父子关系的数据,方便前端数据遍历
4.PermissionAction
package com.ctb.web; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.ctb.dao.PermissionDao; import com.ctb.entity.Permission; import com.zking.framework.ActionSupport; import com.zking.framework.ModelDriver; import com.zking.util.ResponseUtil; import com.zking.util.TreeVo; public class PermissionAction extends ActionSupport implements ModelDriver<Permission>{ private Permission p=new Permission(); private PermissionDao pd=new PermissionDao(); public void menu(HttpServletRequest req, HttpServletResponse resp) throws Exception { // List<TreeVo<Permission>> menus = pd.menus(null, null); // ResponseUtil.writeJson(resp, menus); TreeVo<Permission> menu2 = pd.menu(null, null);//调用顶级节点方法 //向前端响应树形结构的数据 ResponseUtil.writeJson(resp, menu2);//转为json格式 } @Override public Permission getModel() { return p; } }
<?xml version="1.0" encoding="UTF-8"?> <config> <!-- <action path="/blog" type="com.zking.web.BlogAction"> <forward name="list" path="/blogList.jsp" redirect="false" /> <forward name="toList" path="/blog.action?methodName=list" redirect="true" /> <forward name="toEdit" path="/blogEdit.jsp" redirect="false" /> </action> --> <action path="/user" type="com.ctb.web.UserAction"> </action> <action path="/permission" type="com.ctb.web.PermissionAction"> </action> </config>
6.jsp页面--main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="common/header.jsp" %> <!DOCTYPE html > <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <div class="layui-layout layui-layout-admin"> <div class="layui-header"> <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div> <!-- 头部区域(可配合layui 已有的水平导航) --> <ul class="layui-nav layui-layout-left"> <!-- 移动端显示 --> <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft"> <i class="layui-icon layui-icon-spread-left"></i> </li> <!-- Top导航栏 --> <li class="layui-nav-item layui-hide-xs"><a href="">nav 1</a></li> <li class="layui-nav-item layui-hide-xs"><a href="">nav 2</a></li> <li class="layui-nav-item layui-hide-xs"><a href="">nav 3</a></li> <li class="layui-nav-item"> <a href="javascript:;">nav groups</a> <dl class="layui-nav-child"> <dd><a href="">menu 11</a></dd> <dd><a href="">menu 22</a></dd> <dd><a href="">menu 33</a></dd> </dl> </li> </ul> <!-- 个人头像及账号操作 --> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item layui-hide layui-show-md-inline-block"> <a href="javascript:;"> <img src="static/images/bg.jpg" class="layui-nav-img"> 个人中心 </a> <dl class="layui-nav-child"> <dd><a href="">Your Profile</a></dd> <dd><a href="">Settings</a></dd> <dd><a href="login.jsp">Sign out</a></dd> </dl> </li> <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect> <a href="javascript:;"> <i class="layui-icon layui-icon-more-vertical"></i> </a> </li> </ul> </div> <div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <!-- 左侧导航区域(可配合layui已有的垂直导航) --> <ul id="menu" class="layui-nav layui-nav-tree" lay-filter="menu"> </ul> </div> </div> <div class="layui-body"> <!-- 内容主体区域 --> <div style="padding: 15px;">内容主体区域。</div> </div> <div class="layui-footer"> <!-- 底部固定区域 --> 底部固定区域 </div> </div> <script type="text/javascript"> /* 三级菜单 */ layui.use(['jquery'], function(){ let $ = layui.jquery; $.ajax({ url:'${pageContext.request.contextPath }/permission.action?methodName=menu', dataType:'json', success:function(data){ console.log(data); let str=''; str +='<li class="layui-nav-item layui-nav-itemed">'; str +='<a class="" href="javascript:;">'+data.text+'</a>';//顶级节点 //判断节点是否存在子节点 if(!data.hasChildren){ str +='<dl class="layui-nav-child">'; let children = data.children; $.each(children,function(index,node){//二级节点 str +='<dd><a href="javascript:;">'+children[index].text+'</a></dd>'; if(!data.hasChildren){ str +='<dl class="layui-nav-child">'; let children2 =children[index].children; $.each(children2,function(index,node){//三级节点 str +='<dd><a href="javascript:;">'+children2[index].text+'</a></dd>'; }); str +='</dl>'; } }); str +='</dl>'; } str +='</li>'; $("#menu").html(str);//渲染 } }); }); </script> </body> </html>
注:在拼接完成后,最好是对其进行渲染,否则遍历的数据可能会出不来!
三、渲染
1.是什么
渲染是指将树形菜单的数据结构与Layui的动态树组件相结合,最终生成可以展示的树形菜单界面。具体来说,通过调用Layui的tree模块提供的
render
方法,我们可以将树形菜单的数据结构传递给该方法,并指定要渲染的容器的选择器。
2.为什么要渲染
渲染的过程包括解析模板、处理数据、生成HTML结构,并将生成的HTML代码插入到指定的容器中,从而呈现出可交互、可操作的页面。在动态树组件中,渲染的结果是一个可以展开和折叠的树形菜单,方便用户进行查看和操作。
渲染是前端开发中非常重要的一个环节,它将数据与用户界面相结合,实现了用户与应用程序之间的交互。通过渲染,我们可以动态地更新页面内容,根据不同的数据呈现不同的界面,提升用户体验和交互性。
3.特点
1.数据驱动:通过渲染,将数据转化为对应的界面元素,实现了数据的动态呈现。
2.动态更新:渲染可以实现页面的动态更新,当数据发生改变时,只需要更新对应的部分,而不需要重新加载整个页面。
3.可扩展性:通过定义和定制不同的模板或组件,可以根据不同的需求和场景对页面进行渲染,实现灵活的界面设计。
4.分离关注点:渲染实现了前端开发中的关注点分离,将数据和界面逻辑分离开来。
layui动态树就分享到这啦 !!关注博主不迷路😉