運用遞歸生成多級菜單欄


1:還是先上圖 (出於保密原因,這里數據需要塗鴉,請諒解)

可以看到 紅箭頭所指的進度條顯示的是菜單欄豎向的進度,本例中我所有的子菜單一共有300多個 但是大的分類只有6個 

 

 那我們開發的時候是不是要一個個在前端寫好呢?這未免太恐怖也太可怕,加入我們的菜單要添加一個呢 換起來也麻煩。

所以正確的做法是菜單從數據庫中讀取。

2:下面就來展示下數據庫的結構 這里我只要顯示3個字段  id(當前菜單的id 是newid())、pid(當前菜單的父級id)、name(當前菜單的內容)

  在mvc中我微菜單生成專門寫了個方法    

在這個方法里從數據庫中查詢出符合條件的菜單集合

 

方法體 如下   

public ActionResult Navigator2()
{
CheckAuth();
try
{
if (m_user == null)
{
throw new Exception();
}
IList<Menu> li2 = new List<Menu>();
if (Session["Navigator2"] != null)  //將菜單存到session中
{
li2 = Session["Navigator2"] as IList<Menu>;
}
else
{
string strSql = @" sql 根據自己情況去定";

DBHelper db = new DBHelper(Constant.db);
DataTable dt = db.GetDataSet(strSql);
if (dt != null && dt.Rows.Count > 0)
{
li2 = JsonConvert.DeserializeObject<IList<Menu>>(JsonConvert.SerializeObject(dt));
Session["Navigator2"] = li2;
}
}

ViewBag.data = li2;
}
catch (Exception ex)
{
ViewBag.data = null;
}

ViewBag.tage = 2;
return View("~/Views/Shared/Navigator2.cshtml");
}

navigator中 有如下代碼

@{ if (ViewBag.tage == 1)//以為我還有個 Navigator方法 這里用的是 Navigator2 是下面 ViewBag.tage == 2 的方法體
{
@Navigator2.Sys_Menu(ViewBag.data, null, 0);
}
if (ViewBag.tage == 2)
{
@Navigator2.Sys_Menu2(ViewBag.data, "0d7e7ece-8b18-4d63-876b-edad20d29ca2", 0);
}

}

在appcode文件夾中有個 Navigator2

里面遞歸調用方法體如下 

@using app.DA.ef

@helper Sys_Menu2(IEnumerable<app.ViewModel.Menu> entities, string pid, int? Plv)
{
string cls = "";
string Liclass = "";
string iclass = "";

//@Navigator2.Sys_Menu(@ViewBag.data, null,0)第一次調用是傳遞的pid是null 這里調用給出一級菜單的id作為二級菜單的父id
//篩選出一級菜單 entity是所有一級菜單的實體
//將所有的數據集合entities傳遞過去由entity.id作為條件篩選 會篩選出所有符合要求的下一級菜單所需要的集合 這里不要傳遞第一個參數不要傳遞entity 否則共篩選的數據源會越來越小 不符合要求
//第三個參數傳遞0表示是第一級菜單,下面會有判斷if(Plv > 0) 代表是子節點 去找根,否則父空 為根節點 再具體渲染ul li

if (entities != null)//實體不為空開始循環
{

if (Plv == 0)
{
cls = "main-menu";
Liclass = "active opened active";
iclass = "linecons-cog";
}
if (Plv == 1)
{
cls = "";
Liclass = "";
iclass = "entypo-flow-line";
}
if (Plv == 2)
{
cls = "";
Liclass = "";
iclass = "entypo-flow-parallel";
}
if (Plv == 3)
{
cls = "";
Liclass = "";
iclass = "entypo-flow-cascade";
}
if (Plv == 4)
{
cls = "";
Liclass = "";
iclass = "entypo-flow-branch";
}
//var entity = entities.Where(o => o.lvl == 3);
IEnumerable<app.ViewModel.Menu> menu;
menu = entities.Where(o => o._parentId == pid);
Plv++;
if (menu.Count() > 0)//判斷是否有孩子節點 有則繼續進行遞歸 沒有不作任何處理
{
//渲染孩子
<ul id='@cls' class='@cls'>
@foreach (var item in menu)//根據id尋找子節點
{
<li class='@Liclass'>
<a href="javascript:void(0)" onclick="onNodeclickNav(this)" ondblclick="onNodeDblclickNav(this)" name="@item.name" url="@item.url" id="@item.id">
<i class='@iclass'></i>
<span class="title">@item.name</span>
</a>
@Sys_Menu2(entities, item.id, Plv) @*這里將item.id作為篩選條件*@
</li>
}
</ul>
}
}
}

在頁面加載時請求運行此方法之后 就會展示菜單,如果有新添加的菜單只需要在數據庫中添加即可,退出清除session知乎再刷新就能看到最新的效果

 

主題思想就是菜單表里面各級菜單用 id  和pid聯系起來 父級菜單的id為自己菜單的pid。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM