AdminLTE是一款基于bootstrap的后台管理系统的通用模板UI,它的样式美观且较为符合大多数后台管理系统的需求,典型的上|左右|下的布局形式。并且提供了一整套我们开发的时候可能用到的UI样式,比如表格,表单,图表,日历等。非常适合像我这样对样式编排不太擅长的后端开发者。有了它,我们可以不用自己去写很多复杂的html,css。而把更多时间和精力留在后台的开发上。
话不多说,接下来我简要的介绍一下这款模板UI框架的用法。
该款框架是免费的,可以直接在官网下载,下载下来的文件大概有50多兆,包含了所有的html,css,js,还有很多的demo。可供我们随时查阅学习。
先来看看整体的UI的风格吧,是不是挺炫酷的。
可以说几乎所有的后台需要用到的样式都可以从中寻找得到。
由于全套的UI都是静态数据,所以本篇文章着重介绍一下如何动态构造左侧的菜单栏。这应该也是大家比较关心的问题。
所谓的动态就是指的是从数据库或者文件,或者内存中取到的数据。
本人习惯将菜单的数据写成一个静态的js文件,放在项目的js目录中,这样做的好处是不必每次都去从数据库请求,减少IO操作造成的性能和时间损失,当然你也可以从数据库去请求,甚至把菜单数据放入到redis等内存数据库。各类方法都不影响我们前端代码的编写,因为传递的数据格式都是json.
1.将菜单数据写入一个json文件,代码如下。该文件的路径为webapp/static/json/menu.json。
[{
"menuId":"1",
"name": "基本信息",
"controller":"#",
"child": []
},{
"menuId":"2",
"name": "会员管理",
"controller":"#",
"child": [{
"menuId":"3",
"pMenuId":"2",
"name": "会员概览",
"controller":"user/home"
},{
"menuId":"4",
"pMenuId":"2",
"name": "添加会员",
"controller":"user/add"
}]
},{
"menuId":"5",
"name": "销售管理",
"controller":"#",
"child": [{
"menuId":"5",
"pMenuId":"6",
"name": "销售返佣",
"controller":"post/home"
},{
"menuId":"5",
"pMenuId":"7",
"name": "销售报表",
"controller":"post/add"
}]
}]
至于如何写入到文件,我们可以在每次修改菜单以后,先获取菜单的json数据,然后调用如下代码来将菜单的json数据写入文件。
public void generateMenuJson(String jsonStr) { try { File f = new File(ServletActionContext.getServletContext() .getRealPath("/static/json") + "/menu.json"); if (!f.exists()) { f.createNewFile(); } // 定义编码 OutputStreamWriter write = new OutputStreamWriter( new FileOutputStream(f), "UTF-8"); BufferedWriter writer = new BufferedWriter(write); writer.write(jsonStr); writer.close(); } catch (Exception e) { e.printStackTrace(); } }
2.前台ajax获取json数据,并且动态构造出html元素及样式。
主要是用了jQuery ajax异步获取数据,还有就是jquery的append()方法,代码没有什么高深的,只是拼接的时候要很认真。一个取巧的方法是去下载下来的html源码中复制一些关键的代码,避免写错。
1 $(function () { 2 $.ajax({ 3 type: 'get', 4 url:'static/json/menu.json', 5 dataType:'json', 6 success:function(data){ 7 var menu=null; 8 var html=null; 9 var childLen=null;10 var child=null;11 var json=data;12 console.log(json);13 for(var i in json){14 menu=json[i];15 //这里默认展开第一个主菜单16 if(i==0){17 html=$('<li menu-id="'+i+'" class="active treeview "><li>');18 }else{19 html=$('<li menu-id="'+i+'" class="treeview "><li>');20 }21 $(".sidebar .sidebar-menu").append(html);22 html=$('<a href="'+menu.controller+'"><i class="fa fa-dashboard"></i> <span>'+menu.name+'</span><span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a><ul menuUL-id="'+i+'" class="treeview-menu"></ul>');23 $('[menu-id="'+i+'"]').append(html);24 //继续遍历二级菜单25 childLen=menu.child.length;26 for(var j in menu.child){27 child=menu.child[j];28 //这里默认设置第一个子菜单为选中状态29 if(j==0){30 html=$('<li class="active"><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>');31 }else{32 html=$('<li><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>');33 } 34 $('[menuUL-id="'+i+'"]').append(html);35 }36 }37 }38 39 });40 });
相信大家对照demo中的html源码,可以很容易的理解上述代码。我们把原来的左侧菜单的静态html注释掉,引入上述的js文件。看看效果。
这样基本实现了菜单显示的效果。但是还有一个缺点,就是菜单不能根据页面动态变换样式,比如我们在会员概览页面,此时展开的是会员管理,选中的是会员概览。而当我们到了销售管理的时候,我们又希望此时菜单能展开销售管理主菜单并选中相应的子菜单。
要实现这个功能,我们需要在上述的js代码中传入当前访问的链接的菜单id,以及其父级菜单id(如果是最上层的菜单,则其父菜单为自己)。然后根据这两个参数来进行菜单是否展开即是否选中的判断。具体步骤如下。
1.菜单实体如下
package com.wonyen.entity;public class TMenu { private int menuId;//菜单编号 private int pMenuId;//父菜单编号 private String name;//菜单名称 private String controller;//菜单对应的controller public int getMenuId() {
return menuId;
}
public void setMenuId(int menuId) {
this.menuId = menuId;
} public int getpMenuId() { return pMenuId; } public void setpMenuId(int pMenuId) { this.pMenuId = pMenuId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getController() { return controller; } public void setController(String controller) { this.controller = controller; }}
2.获取当前菜单对象,并传入到前台。以会员概览页面为例,代码如下。第8行获取了当前的菜单对象,第9行将其传入到ModelAndView对象中,我们就可以在转发的jsp页面中拿到这个menu对象了。
1 @RequestMapping("partnerHome") 2 public ModelAndView partnerHome(ParamModel pm) { 3 ModelAndView mv = new ModelAndView("back/partner/PartnerList"); 4 mv.addObject("pm", pm); 5 List<TPartnerLevel> partnerLevelList = partnerLevelService 6 .getPartnerLevelList(); 7 mv.addObject("partnerLevelList", partnerLevelList); 8 TMenu menu=menuService.getMenuByController("partnerHome");//获取当前的菜单信息 9 mv.addObject("menu", menu);10 return mv;11 }
3.在每个页面body加入两个属性,menu_id和p_menu_id.如下所示。
<body class="hold-transition skin-red sidebar-mini" menu_id="${menu.menuId}" p_menu_id="${menu.pMenuId}">
4.重新改写原来js代码,让其支持根据当前页面来变换选中的菜单。
$(function () { var menu_id=$('body').attr('menu_id');//菜单id var p_menu_id=$('body').attr('p_menu_id');//父级菜单id $.ajax({ type: 'get', url:'static/json/menu.json', dataType:'json', success:function(data){ var menu=null; var html=null; var childLen=null; var child=null; var json=data; console.log(json); for(var i in json){ menu=json[i]; //如果父菜单是该菜单,就展开 if(menu.menuId==p_menu_id){ html=$('<li menu-id="'+i+'" class="active treeview "><li>'); }else{ html=$('<li menu-id="'+i+'" class="treeview "><li>'); } $(".sidebar .sidebar-menu").append(html); html=$('<a href="'+menu.controller+'"><i class="fa fa-dashboard"></i> <span>'+menu.name+'</span><span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a><ul menuUL-id="'+i+'" class="treeview-menu"></ul>'); $('[menu-id="'+i+'"]').append(html); //继续遍历二级菜单 childLen=menu.child.length; for(var j in menu.child){ child=menu.child[j]; //如果子菜单是该菜单,则设为active选中 if(child.menuId==menu_id){ html=$('<li class="active"><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>'); }else{ html=$('<li><a href="'+child.controller+'"><i class="fa fa-circle-o"></i>'+child.name+'</a></li>'); } $('[menuUL-id="'+i+'"]').append(html); }注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。