版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mzl87/article/details/84455095
现在大多的应用程序(后端)都有菜单,不管是在左侧还是上面,界面基本都是基于现有的UI框架或者网上找的单独的菜单的插件。而实现的方式,大部分都是使用的AJAX形式来完成。前段时间,在总结一些过往的项目时,发现了一些不同的实现的方式,这里想总结一下。所以也就有了这篇文章~~
我建立的测试Demo是使用的MVC的模式,菜单是使用的网上找的第三方插件,实现多级(无限)的顶部菜单。直接上代码来说明~
开始之前,先看下css和js的引用情况以及一些需要的准备工作:
css
<link href="~/scripts/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link rel="stylesheet" href="~/scripts/css/font-awesome.min.css" media="screen">
<link rel="stylesheet" href="~/scripts/css/zlight.menu.css" media="screen">
js
<script src="~/scripts/jquery-1.9.1.min.js"></script>
<script src="~/scripts/bootstrap.min.js"></script>
<script src="~/scripts/jquery.zlight.menu.1.0.min.js"></script>
<!--自定义的js,编写自己的js生成菜单-->
<script src="~/scripts/Home/home.js"></script>
模拟的数据源
/// <summary>
/// 得到数据源
/// </summary>
/// <returns></returns>
private List<MenuModel> GetData()
{
var lstData = new List<MenuModel>();
//顶层菜单
lstData.Add(new MenuModel() { Id = "1", MenuName = "Blog", MenuUrl = "#", ParentId = "#", SortNumb = 1 });
lstData.Add(new MenuModel() { Id = "2", MenuName = "Portfolio", MenuUrl = "#", ParentId = "#", SortNumb = 2 });
lstData.Add(new MenuModel() { Id = "3", MenuName = "Pages", MenuUrl = "#", ParentId = "#", SortNumb = 3 });
lstData.Add(new MenuModel() { Id = "4", MenuName = "Contact", MenuUrl = "#", ParentId = "#", SortNumb = 4 });
lstData.Add(new MenuModel() { Id = "5", MenuName = "About", MenuUrl = "#", ParentId = "#", SortNumb = 5 });
//第二层
lstData.Add(new MenuModel() { Id = "11", MenuName = "LINK1", MenuUrl = "#", ParentId = "1", SortNumb = 1 });
lstData.Add(new MenuModel() { Id = "12", MenuName = "LINK2", MenuUrl = "#", ParentId = "1", SortNumb = 2 });
lstData.Add(new MenuModel() { Id = "13", MenuName = "LINK3", MenuUrl = "#", ParentId = "1", SortNumb = 3 });
lstData.Add(new MenuModel() { Id = "31", MenuName = "LINK1", MenuUrl = "#", ParentId = "3", SortNumb = 1 });
lstData.Add(new MenuModel() { Id = "32", MenuName = "DROPDOWN", MenuUrl = "#", ParentId = "3", SortNumb = 2 });
lstData.Add(new MenuModel() { Id = "33", MenuName = "LINK2", MenuUrl = "#", ParentId = "3", SortNumb = 3 });
//第三层
lstData.Add(new MenuModel() { Id = "321", MenuName = "LINK1", MenuUrl = "#", ParentId = "32", SortNumb = 1 });
lstData.Add(new MenuModel() { Id = "322", MenuName = "LINK2", MenuUrl = "#", ParentId = "32", SortNumb = 2 });
lstData.Add(new MenuModel() { Id = "323", MenuName = "LINK3", MenuUrl = "#", ParentId = "32", SortNumb = 3 });
lstData.Add(new MenuModel() { Id = "324", MenuName = "DROPDOWN", MenuUrl = "#", ParentId = "32", SortNumb = 4 });
//第四层
lstData.Add(new MenuModel() { Id = "3241", MenuName = "LINK1", MenuUrl = "#", ParentId = "324", SortNumb = 1 });
lstData.Add(new MenuModel() { Id = "3242", MenuName = "LINK2", MenuUrl = "#", ParentId = "324", SortNumb = 2 });
return lstData;
}
后台菜单实现需要的方法
/// <summary>
/// 生成菜单拼接字符串
/// </summary>
/// <returns></returns>
private string GenerateMenu()
{
StringBuilder sb = new StringBuilder();
var lstAll = GetData();
var lstParent = lstAll.FindAll(x => x.ParentId == "#").ToList();
var lstChilds = lstAll.FindAll(x => x.ParentId != "#").ToList();
if (lstParent.Any())
{
foreach (var top in lstParent)
{
var lstOnes = lstChilds.FindAll(x => x.ParentId == top.Id).OrderBy(x => x.SortNumb).ToList();
if (lstOnes.Any())
{
sb.Append("<li class=\"zlight-dropdown\">")
.AppendFormat("<a href = \"{0} \"> {1}<i class=\"icon-angle-down\"></i></a>", top.MenuUrl, top.MenuName)
.Append("<ul class=\"zlight-submenu\">");
GetChild(sb, lstChilds, lstOnes);
sb.Append("</ul></li > ");
}
else
{
sb.AppendFormat("<li><a href = \"{0} \"> {1} </a></li>", top.MenuUrl, top.MenuName);
}
}
}
return sb.ToString();
}
/// <summary>
/// 得到子菜单项
/// </summary>
/// <param name="sb">StrignBuilder对象</param>
/// <param name="lstChilds">所有子节点集合</param>
/// <param name="lstOnes">“父”节点集合</param>
private static void GetChild(StringBuilder sb, List<MenuModel> lstChilds, List<MenuModel> lstOnes)
{
foreach (var chld in lstOnes)
{
var lstTwos = lstChilds.FindAll(x => x.ParentId == chld.Id).OrderBy(x => x.SortNumb).ToList();
if (lstTwos.Any())
{
sb.Append("<li class=\"zlight-dropdown\">")
.AppendFormat("<a href = \"{0} \"> {1}<i class=\"icon-angle-down\"></i></a>", chld.MenuUrl, chld.MenuName)
.Append(" <ul class=\"zlight-submenu\">");
GetChild(sb, lstChilds, lstTwos);
sb.Append("</ul></li> ");
}
else
{
sb.AppendFormat("<li><a href = \"{0} \" target = \"_blank\"> {1} </a></li>", chld.MenuUrl, chld.MenuName);
}
}
}
1、Ajax方式
html部分
<div class="row">
<div class="col-lg-12">
<h4>第一种(AJAX):</h4>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<nav id="zlight-nav">
<ul id="zlight-main-nav">
<li class="zlight-active"><a href="/">Home</a></li>
</ul>
<!-- MOBILE NAV -->
<div id="zlight-mobile-nav">
<span>Menu</span>
<i class="icon-reorder zlight-icon"></i>
<select></select>
</div>
</nav> <!-- nav close -->
</div>
</div>
js(注意放到页面加载完成事件中)
$.ajax({
url: "/Home/GetTopMenu",
type: 'POST',
async: false,
dataType: 'text',
timeout: 20000,
error: function () {
alert('Error loading XML document');
},
success: function (result) {
$("#zlight-main-nav").append(result);
$('#zlight-nav').zlightMenu();
}
});
后台的Action方法
[HttpPost]
public ActionResult GetTopMenu()
{
return Content(GenerateMenu());
}
2、ViewBag方式
html部分
<div class="row">
<div class="col-lg-12">
<h4>第二种(ViewBag):</h4>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<nav id="zlight-nav" class="razer">
<ul id="zlight-main-nav">
<li class="zlight-active"><a href="/">Home</a></li>
@Html.Raw(@ViewBag.TopMenu)
</ul>
<!-- MOBILE NAV -->
<div id="zlight-mobile-nav">
<span>Menu</span>
<i class="icon-reorder zlight-icon"></i>
<select></select>
</div>
</nav>
</div>
</div>
js
$('.razer').zlightMenu();
后台代码
// GET: Home
public ActionResult Index()
{
ViewBag.TopMenu = GenerateMenu();
return View();
}
3、Razer递归方式(很少用)
html部分
<div class="row">
<div class="col-lg-12">
<h4>第三种(Razer递归):</h4>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<nav id="zlight-nav" class="razerdigui">
<ul id="zlight-main-nav">
<li class="zlight-active"><a href="/">Home</a></li>
@{
var lstData = ViewBag.MenuDataList as List<MenuModel>;
@helper DisplayChildMenu(List<MenuModel> lstChilds, List<MenuModel> lstOnes)
{
foreach (var chld in lstOnes)
{
var lstTwos = lstChilds.FindAll(x => x.ParentId == chld.Id).OrderBy(x => x.SortNumb).ToList();
if (lstTwos.Any())
{
<li class="zlight-dropdown">
<a href="@chld.MenuUrl" target="_blank">@chld.MenuName <i class="icon-angle-down"></i></a>
<ul class="zlight-submenu">
@DisplayChildMenu(lstChilds, lstTwos)
</ul>
</li>
}
else
{
<li><a href="@chld.MenuUrl" target="_blank">@chld.MenuName</a></li>
}
}
}
var lstParent = lstData.FindAll(x => x.ParentId == "#").ToList();
var lstChilds = lstData.FindAll(x => x.ParentId != "#").ToList();
if (lstParent.Any())
{
foreach (var top in lstParent)
{
var lstOnes = lstChilds.FindAll(x => x.ParentId == top.Id).OrderBy(x => x.SortNumb).ToList();
if (lstOnes.Any())
{
<li class="zlight-dropdown">
<a href="@top.MenuUrl">@top.MenuName <i class="icon-angle-down"></i></a>
<ul class="zlight-submenu">
@DisplayChildMenu(lstChilds, lstOnes)
</ul>
</li>
}
else
{
<li><a href="@top.MenuUrl">@top.MenuName</a></li>
}
}
}
}
</ul>
<!-- MOBILE NAV -->
<div id="zlight-mobile-nav">
<span>Menu</span>
<i class="icon-reorder zlight-icon"></i>
<select></select>
</div>
</nav>
</div>
</div>
js部分
$('.razerdigui').zlightMenu();
后台部分
// GET: Home
public ActionResult Index()
{
ViewBag.MenuDataList = GetData();
return View();
}
后记:在非MVC模式下,第一中Ajax方式是非常常用的,即使在MVC模式下仍常用。第二种和第三中在MVC模式下用都可以,Razer的递归之前并没有注意到,一次突发奇想就度娘了下,结果还真有。至于需要用哪种,看个人吧