AdminLTE是一款基於bootstrap的後臺管理系統的通用模板UI,它的樣式美觀且較爲符合大多數後臺管理系統的需求,典型的上|左右|下的佈局形式。而且提供了一整套咱們開發的時候可能用到的UI樣式,好比表格,表單,圖表,日曆等。很是適合像我這樣對樣式編排不太擅長的後端開發者。有了它,咱們能夠不用本身去寫不少複雜的html,css。而把更多時間和精力留在後臺的開發上。css
話很少說,接下來我簡要的介紹一下這款模板UI框架的用法。html
官網:https://adminlte.io/前端
該款框架是免費的,能夠直接在官網下載,下載下來的文件大概有50多兆,包含了全部的html,css,js,還有不少的demo。可供咱們隨時查閱學習。jquery
先來看看總體的UI的風格吧,是否是挺炫酷的。web
能夠說幾乎全部的後臺須要用到的樣式均可以從中尋找獲得。ajax
因爲全套的UI都是靜態數據,因此本篇文章着重介紹一下如何動態構造左側的菜單欄。這應該也是你們比較關心的問題。redis
所謂的動態就是指的是從數據庫或者文件,或者內存中取到的數據。數據庫
本人習慣將菜單的數據寫成一個靜態的js文件,放在項目的js目錄中,這樣作的好處是沒必要每次都去從數據庫請求,減小IO操做形成的性能和時間損失,固然你也能夠從數據庫去請求,甚至把菜單數據放入到redis等內存數據庫。各種方法都不影響咱們前端代碼的編寫,由於傳遞的數據格式都是json.json
1.將菜單數據寫入一個json文件,代碼以下。該文件的路徑爲webapp/static/json/menu.json。bootstrap
[{
"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); } } } }); });
通過上述步驟之後,咱們就能夠獲得更爲合理的左側菜單了。來看看效果吧。
--會員概覽頁
---會員添加頁
看,已經實現了咱們想要的效果。若是你也正在尋找一個後臺的UI,趕忙試試吧。
-----------------------------------------------------------------------------------------------2018年4月2日更新-------------------------------------------------------------------------------------------------------------------------------------------------------------------
最近發現一種新的記錄菜單選中狀況的方法,就是利用瀏覽器的緩存,每次點擊菜單的時候,將點擊的菜單Id記錄到瀏覽器緩存中,而後加載菜單的時候經過緩存中的菜單來比對,匹配成功就將其展開而且設爲active.這種方法就不須要在服務端傳入當前的菜單了,簡單了不少。
1 $(function () { 2 var firstLvId=getFirstLvMenu();//一級菜單 3 var secondLvId=getSecondLvMenu();//二級菜單 4 var thirdLvId=getThirdLvMenu();//三級菜單 5 $.ajax({ 6 type: 'get', 7 url:'/menu/tree', 8 dataType:'json', 9 success:function(data){ 10 var menu=null; 11 var html=null; 12 var childLen=null; 13 var child=null; 14 var json=data; 15 console.log(json); 16 for(var i in json){ 17 menu=json[i]; 18 //若是父菜單是該菜單,就展開 19 if(menu.menuId==firstLvId){ 20 html=$('<li menu-id="'+i+'" class="active treeview "><li>'); 21 }else{ 22 html=$('<li menu-id="'+i+'" class="treeview "><li>'); 23 } 24 $(".sidebar .sidebar-menu").append(html); 25 html=$('<a class="first-menu" href="../'+menu.menuSrc+'" onclick="saveFirstLvMenu('+menu.menuId+')"><i class="fa fa-dashboard"></i> <span>'+menu.menuName+'</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>'); 26 $('[menu-id="'+i+'"]').append(html); 27 //繼續遍歷二級菜單 28 childLen=menu.child.length; 29 for(var j in menu.child){ 30 child=menu.child[j]; 31 //若是子菜單是該菜單,則設爲active選中 32 if(child.menuId==secondLvId){ 33 html=$('<li class="active"><a class="second-menu" href="../'+child.menuSrc+'" onclick="saveSecondLvMenu('+child.menuId+')"><i class="fa fa-circle-o"></i>'+child.menuName+'</a></li>'); 34 }else{ 35 html=$('<li><a class="second-menu" href="../'+child.menuSrc+'" onclick="saveSecondLvMenu('+child.menuId+')"><i class="fa fa-circle-o"></i>'+child.menuName+'</a></li>'); 36 } 37 $('[menuUL-id="'+i+'"]').append(html); 38 } 39 } 40 } 41 42 }); 43 }); 44 function saveFirstLvMenu(menuId) { 45 var id = JSON.stringify(menuId); 46 window.sessionStorage.setItem("firstMenuId", id); 47 } 48 49 function saveSecondLvMenu(menuId) { 50 var id = JSON.stringify(menuId); 51 window.sessionStorage.setItem("secondMenuId", id); 52 } 53 54 function saveThirdLvMenu(menuId) { 55 var id = JSON.stringify(menuId); 56 window.sessionStorage.setItem("thirdMenuId", id); 57 } 58 59 function getFirstLvMenu() { 60 return JSON.parse(window.sessionStorage.getItem("firstMenuId")); 61 } 62 function getSecondLvMenu() { 63 return JSON.parse(window.sessionStorage.getItem("secondMenuId")); 64 } 65 function getThirdLvMenu() { 66 return JSON.parse(window.sessionStorage.getItem("thirdMenuId")); 67 }