其中后端代码不包含权限控制,同时支持二级(无子菜单) 和 三级菜单(无子菜单)。

1、layui前端代码:(其他前端框架实现方法通用,不过需要修改js中append对应标签元素即可)

 <div class="layui-side layui-bg-black">
<div class="layui-side-scroll">
<!-- 左侧导航区域(可配合layui已有的垂直导航) -->
<ul class="layui-nav layui-nav-tree" id="chuizhi" lay-filter="test"></ul>
</div>
</div> <div class="layui-body">
<!-- 内容主体区域 -->
<iframe name="iframe" src="/test/welcome" width="100%" height="100%"
frameborder="no" border="0" scrolling="auto"></iframe>
</div> <div class="layui-footer">
<!-- 底部固定区域 -->
© myzy.cn -
</div> <script> function isArrayFn(value){//用于判断对象是否为数组.
if (typeof Array.isArray === "function") {
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === "[object Array]";
}
}
//JavaScript代码区域
layui.use(['form', 'layedit','element', 'layer','laydate','table'], function(){
var table = layui.table
,element = layui.element
,form = layui.form
,layer = layui.layer
,layedit = layui.layedit
,laydate = layui.laydate
,$ = layui.jquery;
37 //动态渲染树形菜单
$.post("/todo/treeData", function (data){//请求后端返回对应json
var menu1 = [];//所有一级菜单名称数组
for (var key in data) {
menu1.push(key);
}
var len = menu1.length;
for(var i=0;i<len;i++){
$("#chuizhi").append(`<li class="layui-nav-item"><a href="javascript:;">${menu1[i]}</a>
<dl class="layui-nav-child ${menu1[i]}">
</dl></li>`);//一级菜单(有子菜单)
let ss = data[menu1[i]];
if(isArrayFn(ss)){
for(let j=0;j<ss.length;j++){
$("."+menu1[i]).append(`<dd class="twoMenu"><a href="${ss[j].url}" target="iframe">&nbsp;&nbsp;${ss[j].name}</a></dd>`);//只到(没有子菜单)二级菜单
}
}else{
let arr = [];
for(var key in ss){
arr = ss[key];
$("."+menu1[i]).append(`<li class="layui-nav-item twoMenu"><a href="javascript:;">&nbsp;${key}</a>
<dl class="layui-nav-child ${key}">
</dl></li>`);//二级菜单(有子菜单)
for(let j=0;j<arr.length;j++){
$("."+key).append(`<dd><a href="${arr[j].url}" target="iframe">&nbsp;&nbsp;${arr[j].name}</a></dd>`);//只到(没有子菜单)三级菜单
}
}
}
}
element.render();//element.init();//全部更新,用于动态渲染之后的挂载 (2)
/**用于菜单显示效果:点击其他菜单,原来打开的菜单自动关闭*/
$(".twoMenu,#chuizhi>li").on("click",function () {
if(!$(this).hasClass("layui-nav-itemed")){
$(this).removeClass("layui-nav-itemed");
if($(this).children().children().hasClass("layui-nav-itemed")){
$(this).children().children().removeClass("layui-nav-itemed");
}
}else if($(this).hasClass("layui-nav-itemed")){
$(this).addClass("layui-nav-itemed");
$(this).siblings().removeClass("layui-nav-itemed");
if(!$(this).children().children().hasClass("layui-nav-itemed")){
$(this).children().children().removeClass("layui-nav-itemed");
}
}
}) })
});
</script>

2.java后端代码:用于返回给前端 菜单(json) 数据

 @Override//其中menu_duidMapper为装载的dao层接口
public Map<String, Object> queryJsonMenus() {
Map<String, Object> mapR = new LinkedHashMap<String, Object>();
//Map<String,Map<String,List<Map<String,String>>>> mapSan = new LinkedHashMap<>();//前端三级菜单json在后端表现形式
//Map<String,List<Map<String,String>>> mapTwo = new LinkedHashMap<>();//前端二级菜单json在后端表现形式
List<String> oneLevelMenuId = menu_duidMapper.selectGoodsMenuIdOneJ();//一级菜单id
List<String> TwoLevelPId = menu_duidMapper.selectGoodsParentIdTwoJ(); //二级菜单fuid
List<String> grandIdThreeJ = menu_duidMapper.selectGoodsGrandIdThreeJ();//三级菜单祖父id
String oneName = null;
String twoName = null;
List<Map<String,String>> msp = null;
List<String> threePid = null;
for(String oneMid : oneLevelMenuId){
Map<String,List<Map<String,String>>> mapTwo = new LinkedHashMap<>();//这里不可以使用单例,所以只能生命在for循环内部
for(String erPid : TwoLevelPId){
if(oneMid.equals(erPid)){
oneName = menu_duidMapper.selectGoodsTypeByMenuId(oneMid);//根据一级菜单menuid查询对应名称
msp = menu_duidMapper.selectGoodsMapByPid(erPid);//根据二级菜单父id查找对应二级map
mapR.put(oneName,msp);//填充一级菜单对应的二级菜单(无子菜单)
}else{
continue;
}
}
for(String sanGpid : grandIdThreeJ){
if(oneMid.equals(sanGpid)){
oneName = menu_duidMapper.selectGoodsTypeByMenuId(oneMid);//
threePid = menu_duidMapper.selectGoodsParentIdThreeJByGrandId(sanGpid);//根据祖父id查询父id并去重
for(String tpid : threePid){
msp = menu_duidMapper.selectGoodsMapByPidAndGpid(tpid,sanGpid);//根据祖父id和父id查询对应map
twoName = menu_duidMapper.selectGoodsTypeByMenuId(tpid);//根据三级菜单父id查询对应二级菜单
//System.out.println(twoName);
mapTwo.put(twoName,msp);//填充二级菜单(有子菜单)和对应三级菜单(物资菜单)
}
mapR.put(oneName,mapTwo);//填充一级菜单所对应的二(有子菜单)三(无子菜单)级菜单
}else{
continue;
}
}
}
return mapR;
}

3.数据库表结构

 DROP TABLE IF EXISTS `menu_duid`;
CREATE TABLE `menu_duid` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`menu_id` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单id',
`parent_id` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '菜单父id',
`grand_pid` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '菜单爷爷id',
`url` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单路径',
`romaker` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 96 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

4.ajax返回的json数据格式为

 {
"新闻资讯":{
"企业新闻":[
{
"menuID":"010101",
"name":"xxx",
"url":"/test/petroleum010101"
},
{
"menuID":"010102",
"name":"xxx",
"url":"/test/mAsphalt010102"
}
],
"行业新闻":[
{
"menuID":"010201",
"name":"xxx",
"url":"/test/petroleum010201"
},
{
"menuID":"010202",
"name":"xxx",
"url":"/test/mAsphalt010202"
}
]
},
"行业报告":{
"日报":[
{
"menuID":"020101",
"name":"xxx",
"url":"/test/petroleum020101"
},
{
"menuID":"020102",
"name":"xxx",
"url":"/test/mAsphalt020102"
}
],
"周报":[
{
"menuID":"020201",
"name":"xxx",
"url":"/test/petroleum020201"
},
{
"menuID":"020202",
"name":"xxxx",
"url":"/test/mAsphalt020202"
}
],
"月报":[
{
"menuID":"",
"name":"xxx",
"url":"/test/petroleum020301"
},
{
"menuID":"",
"name":"xxx",
"url":"/test/mAsphalt020302"
}
],
"年报":[
{
"menuID":"",
"name":"xxx",
"url":"/test/petroleum020401"
},
{
"menuID":"",
"name":"xxx",
"url":"/test/mAsphalt020402"
}
]
},
"政策法规":[
{
"menuID":"",
"name":"xxx",
"url":"/test/petroleum0301"
},
{
"menuID":"",
"name":"xxx",
"url":"/test/mAsphalt0302"
}
]
}

5.对应查询的sql语句省略,这个比较简单,只用到了普通查询和几个子查询。。。。

动态渲染左侧菜单栏 :menu tree 动态渲染的更多相关文章

  1. vue 动态渲染数据很慢或不渲染

    vue 动态渲染数据很慢或不渲染 原因是因为vue检测速度很慢,因为多层循环了,在VUE 2.x的时候还能渲染出来,1.x的时候压根渲染不出来.解决方式:在动态改变数据的方法,第一行加上 this.$ ...

  2. Android动态修改ToolBar的Menu菜单

    Android动态修改ToolBar的Menu菜单 效果图 实现 实现很简单,就是一个具有3个Action的Menu,在我们滑动到不同状态的时候,把对应的Action隐藏了. 开始上货 Menu Me ...

  3. 细说后端模板渲染、客户端渲染、node 中间层、服务器端渲染(ssr)

    细说后端模板渲染.客户端渲染.node 中间层.服务器端渲染(ssr) 前端与后端渲染方式的发展大致经历了这样几个阶段:后端模板渲染.客户端渲染.node 中间层.服务器端渲染(ssr). 1. 后端 ...

  4. [转贴]Cocos2d-x3.2与OpenGL渲染总结(一)Cocos2d-x3.2的渲染流程

    看了opengles有一段时间了,算是了解了一下下.然后,就在基本要决定还是回归cocos2dx 3.2的,看了这篇好文章,欣喜转之~ 推荐看原帖: Cocos2d-x3.2与OpenGL渲染总结(一 ...

  5. 某APK中使用了动态注册BroadcastReceiver,Launcher中动态加载此APK出现java.lang.SecurityException异常的解决方法

    在某APK中,通过如下方法动态注册了一个BroadcastReceiver,代码参考如下: @Override protected void onAttachedToWindow() { super. ...

  6. WebStorm设置左侧菜单栏背景和字体设置

    WebStorm左侧菜单栏 webstorm是一款前端IDE利器,个人感觉黑色的背景比较炫酷,刚开始从网上下载的主题只能修改编辑窗口的背景色,经过查询资料终于把左边菜单栏的背景色也修改了. 第一步:点 ...

  7. 模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(上)

      我们大部分人都发过动态,想必都知道发动态.回复评论.删除动态的整个过程,那么作为初学者,要模仿这些功能有点复杂的,最起码表的关系得弄清楚~~ 先把思路理一下: (1)用户登录,用session读取 ...

  8. PHP系统左侧菜单栏的管理与实现

    在日常的开发工作中,面对后台的日益增长的业务,以及后期业务的迭代开发,通常会选择添加菜单栏的形式来扩充业务功能,同样日益增长的后台菜单选项也为我们后期的维护,产生了一定的困难性.为此我总结出自己关于左 ...

  9. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

随机推荐

  1. Linux 命令行作弊工具安利

    本文转自 微信公众号<Linux爱好者>的一篇文章,觉得工具非常好使,且极具使用价值,所以在此安利一下 Linux 用户的福音,记忆力解放!快速调用复杂命令 刚学的一句新命令,才用完就忘了 ...

  2. Srping的IOC

    XML方式: IOC:控制反转的底层原理就是:工厂模式+反射+配置文件DI:依赖注入就是通过配置文件设置属性值 BeanFactory 是老版本的工厂类:调用getBean的时候,才会生成类的实例Ap ...

  3. IDEA中Lombok插件的安装及使用

    这个插件的好处在于可以让我们的代码更简洁,减少一些重复的工作,最常用的就是@Data注解,比如在实体类上使用@Data注解,实体类的各个属性就不需要书写get和set方法. 安装方法: 1.File→ ...

  4. linux那些事儿

    Linux只是一个操作系统内核而已,而GNU提供了大量的自由软件来丰富在其之上的各种应用程序.我们常说的linux实际是GNU/Linux,GNU是一个自由的操作系统.绝大多数基于Linux内核的操作 ...

  5. 【论文阅读】3DMM-A Morphable Model for The Synthesis of 3D Faces

    前言 参考 1. 2. 完

  6. Centos7.3之K8S安装初体验

    容器是发展趋势,所以是时候从虚拟机中脱离出来,投入到容器化的怀抱中了. 曾经试过安装k8s,都没有成功,各种乱七八糟的报错,于是一拖再拖,这次总算发现一个可以快速部署的工具,终于安装成功了. 这个k8 ...

  7. activiti学习3:流程引擎对象和流程引擎配置对象

    目录 activiti学习3:流程引擎对象和流程引擎配置对象 一.activiti的简单使用流程 二.流程引擎配置对象ProcessEngineConfiguration的介绍 三.activiti配 ...

  8. 【ztree】获取根节点

    var node = treeObj.getNodesByFilter(function (node) { return node.level == 0 }, true);

  9. ThinkPHP3开发模式,控制器操作,配置文件,框架语法

    ThinkPHP的开发模式 tp框架有两种使用模式:开发模式(调试模式),一种是生产模式(运行模式) define('APP_DEBUG', true);  //调试模式 define('APP_DE ...

  10. ProxyGenerator proxy = new ProxyGenerator(); 代理+拦截器模式

    所谓代理,就是不直接访问目标对象,而是由中间对象生成一个目标代理类,由中间代理对象来代理目标对象的方法.Java里面有JDK和CGLIB代理.C#里面则使用Castle代理.nuget引用如下: &l ...