前面的教程和大家一起學習了系統登錄部分的開發,登錄之後呢我們需要展示管理平臺的主頁,通常,管理系統的主頁是這樣佈局的:
- 頂部:基本包括系統名稱、主功能菜單、用戶名稱和頭像
- 中間部分:左側是主功能菜單下的子菜單,右側是子菜單對應的頁面
- 底部: 技術支持信息,也就是開發者給自己打的廣告😄
上面說的這種佈局模式其實就是邊界佈局(Border Layout)。也就是,下面截圖這個樣子:
接下來,我們就一起來學習一下如何實現主頁中的頂部和左側菜單吧
一、菜單欄效果演示
菜單部分最終的效果是,點擊頂部菜單,相應的子菜單會在左側加載出來;點擊左側的菜單,正文部分會加載該部分頁面。無圖言卵,頂部菜單和左側菜單欄的實現後效果:
二、實現頂部菜單(一級菜單)
在介紹代碼實現之前,我們先來思考一下頂部菜單實現的原理。
首先,我們頁面中加上一個<ul>用來展示菜單內容,在index頁面加載時調用initTopMenu()函數初始化該<ul>。那菜單的內容從哪裏來呢?頁面上寫死嗎?當然不行啦,不用的用戶登錄進來需要顯示不同的菜單,所以,我們需要從後臺返回當前登錄用戶的菜單選項。當我們點擊頂部菜單時,switchMenu()函數響應點擊事件並加載該菜單的子菜單到頁面左側。
1、index.jsp中<body>元素中加上<header>,header中包含了一個id爲"nav-left"的<ul>用來展示頂部菜單:
<header>
<nav class="navbar navbar-default navbar-fixed-top">
<a href="javascript:void(0);" class="navbar-brand" id="navbar-brand">OMS System </a>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav" id="nav-left"> </ul>
<ul class="nav navbar-nav navbar-right" id="nav-right" style="height: 100%">
<li style="padding-top:5px;"><a href="javascript:void(0);" style="vertical-align: middle;display:inline;padding-left:3px;"> ${user_cname}, 歡迎登錄</a></li>
</ul>
</div>
</nav>
</header>
2、加載index頁面時,初始化頂部菜單:
//初始化頂部菜單
function initTopMenu(topMenuList) {
if (topMenuList == '' || topMenuList == undefined) {
alert('系統初始化失敗,請聯繫管理員');
}
var topMenus = JSON.parse(topMenuList);
for (let i = 0; i < topMenus.length; i++) {
let topMenu = topMenus[i];
let m_id = topMenu.m_id;
let m_name = topMenu.m_name;
let m_icon = topMenu.m_icon;
let liClass = '';
if (i == 0) {
liClass = 'class="newactive"';
//保存第一個菜單的id,用戶加載左側菜單
window.sessionStorage.setItem('first_module_id', m_id);
}
$('#nav-left').append('<li '+liClass+'><a href="javascript:void(0)" onclick="switchMenu(this)" data-mid="'+m_id+'"><i class="' + m_icon + '"></i> '+ m_name +'</a></li>')
}
}
3、加載index頁面時調用的controller,在該controller中返回頂部菜單和左側菜單內容
@RequestMapping("/index")
public ModelAndView index(HttpServletRequest request, HttpServletResponse response) {
ModelAndView model = new ModelAndView(INDEX_PAGE);
String username = request.getSession().getAttribute("username").toString();
//根據用戶名獲取菜單
List<UserRoleModule> menuList = userRoleModuleService.getMenuByUsername(username);
List<UserRoleModule> topMenuList = new ArrayList<UserRoleModule>();
List<UserRoleModule> sideMenuList = new ArrayList<UserRoleModule>();
//分別保存頂部菜單和左側菜單
for (UserRoleModule menu : menuList) {
if ("0".equals(menu.getM_parent().toString())) {
topMenuList.add(menu);
} else {
sideMenuList.add(menu);
}
}
if (menuList.size() > 0) {
model.addObject("user_cname", menuList.get(0).getCname());
} else {
model.addObject("user_cname", username);
}
String topMenus = JSON.toJSONString(topMenuList);
String sideMenus = JSON.toJSONString(sideMenuList);
model.addObject("topMenuList", topMenus);
model.addObject("page", "index.jsp page's value");
model.addObject("current_user", username);
return model;
}
三、實現左側菜單(二級菜單)
index頁面加載時,左側菜單內容也由後臺返回,並且由initSideMenu()函數將菜單在頁面中顯示出來;當點擊頂部菜單時,switchMenu()函數將對應的二級菜單展示出來。
左側菜單頁面<ul>元素
<aside class="main-sidebar">
<section class="sidebar">
<ul id="sidebar-menu" class="sidebar-menu" data-widget="tree">
</section>
<aside>
initSideMenu()函數
//初始化左側菜單
function initSideMenu(sideMenuList, topMenuSelected) {
if (sideMenuList == '' || sideMenuList == undefined) {
alert('系統初始化失敗,請聯繫管理員');
}
var sideMenus = JSON.parse(sideMenuList);
var htmlContent = '';
let index = 0;//用於控制第一個菜單爲展開狀態,其他則爲收起狀態
for (let i = 0; i < sideMenus.length; i++) {
let sideMenu = sideMenus[i];
if (sideMenu.m_parent + '' == topMenuSelected+'') {
index ++;
htmlContent += '<li class="treeview ';
if (index == 1) {
htmlContent += 'active menu-open">';
} else {
htmlContent += '">';
}
htmlContent += '<a href="javascript:void(0);"><i class="'+sideMenu.m_icon+'"></i><span><strong> '+sideMenu.m_name+'</strong></span>'+'<span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a>';
htmlContent += '<ul class="treeview-menu">';
for (let j = 0; j < sideMenus.length; j++) {
if (sideMenu.m_id == sideMenus[j].m_parent) {
htmlContent += '<li><a href="javascript:void(0)" onclick="chooseMenu(this)" class="myLeftMenu" data="<%=basePath%>'+sideMenus[j].url+'"><i class="'+sideMenus[j].m_icon+'"></i> '+sideMenus[j].m_name+'</a></li>';
}
}
htmlContent += '</ul></li>';
}
}
$('#sidebar-menu').empty();
$('#sidebar-menu').append(htmlContent);
}
四、菜單聯動
使用switchMenu()函數來聯動菜單
//點擊頂部菜單,切換左側菜單
function switchMenu(e) {
//修改點擊後樣式
var parentClass = $(e).parent().attr('class');
if (parentClass != '' && parentClass != undefined && parentClass.indexOf('newactive') > -1) {
return;
}
var bros = $(e).parent().parent().children();
for (let i = 0; i < bros.length; i++) {
let bro = bros[i];
$(bro).removeClass('newactive');
}
var parent = $(e).parent();
$(parent).addClass('newactive');
//切換左側菜單
var parent_id = $(e).attr('data-mid');
var sideMenuList = '${sideMenuList}';
initSideMenu(sideMenuList, parent_id);
}
五、本篇結束語
一級菜單和二級菜單的實現原理並不複雜,總結一下就是:
- 後臺從數據庫查詢當前登錄用戶的菜單,返回一級菜單和二級菜單內容到前端
- 頁面加載時就初始化解析一級和二級菜單,並渲染到頁面中
- 當點擊一級菜單時,重新渲染二級菜單
當然,實現起來還是有很多細節需要考慮;並且,要想菜單看起來好看點,還需要很多CSS樣式的點綴,在上文博客中並非一應俱全,需要獲取更多源碼的同學歡迎加羣呀:584017112