现在大多的应用程序(后端)都有菜单,不管是在左侧还是上面,界面基本都是基于现有的UI框架或者网上找的单独的菜单的插件。而实现的方式,大部分都是使用的AJAX形式来完成。前段时间,在总结一些过往的项目时,发现了一些不同的实现的方式,这里想总结一下。所以也就有了这篇文章~~
我建立的测试Demo是使用的MVC的模式,菜单是使用的网上找的第三方插件,实现多级(无限)的顶部菜单。直接上代码来说明~
开始之前,先看下css和js的引用情况以及一些需要的准备工作:
css
js
模拟的数据源
///
/// 得到数据源
///
///
private List GetData()
{
var lstData = new List();
//顶层菜单
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;
}
后台菜单实现需要的方法
///
/// 生成菜单拼接字符串
///
///
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("")
.AppendFormat(" {1}", top.MenuUrl, top.MenuName)
.Append("");
GetChild(sb, lstChilds, lstOnes);
sb.Append("
");
}
else
{
sb.AppendFormat(" {1} ", top.MenuUrl, top.MenuName);
}
}
}
return sb.ToString();
}
///
/// 得到子菜单项
///
/// StrignBuilder对象
/// 所有子节点集合
/// “父”节点集合
private static void GetChild(StringBuilder sb, List lstChilds, List 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("")
.AppendFormat(" {1}", chld.MenuUrl, chld.MenuName)
.Append(" ");
GetChild(sb, lstChilds, lstTwos);
sb.Append("
");
}
else
{
sb.AppendFormat(" {1} ", chld.MenuUrl, chld.MenuName);
}
}
}
1、Ajax方式
html部分
第一种(AJAX):
- Home
Menu
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部分
第二种(ViewBag):
- Home
@Html.Raw(@ViewBag.TopMenu)
Menu
js
$('.razer').zlightMenu();
后台代码
// GET: Home
public ActionResult Index()
{
ViewBag.TopMenu = GenerateMenu();
return View();
}
3、Razer递归方式(很少用)
html部分
第三种(Razer递归):
- Home
@{
var lstData = ViewBag.MenuDataList as List;
@helper DisplayChildMenu(List lstChilds, List lstOnes)
{
foreach (var chld in lstOnes)
{
var lstTwos = lstChilds.FindAll(x => x.ParentId == chld.Id).OrderBy(x => x.SortNumb).ToList();
if (lstTwos.Any())
{
-
@chld.MenuName
@DisplayChildMenu(lstChilds, lstTwos)
}
else
{
- @chld.MenuName
}
}
}
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())
{
-
@top.MenuName
@DisplayChildMenu(lstChilds, lstOnes)
}
else
{
- @top.MenuName
}
}
}
}
Menu
js部分
$('.razerdigui').zlightMenu();
后台部分
// GET: Home
public ActionResult Index()
{
ViewBag.MenuDataList = GetData();
return View();
}
后记:在非MVC模式下,第一种Ajax方式是非常常用的,即使在MVC模式下仍常用。第二种和第三中在MVC模式下用都可以,Razer的递归之前并没有注意到,一次突发奇想就度娘了下,结果还真有。至于需要用哪种,看个人吧