在做許可權系統的時候,需要有一個樹形的菜單。就是一個樹形菜單的樣式
但問題是,我們可以實現寫死的樹形菜單。什麼是寫死的?就是在前台代碼中寫好要載入的樹形菜單是什麼樣子的。但是我們許可權系統的要求是動態載入樹形菜單,也就是根據資料庫裡面表的內容動態載入。
我首先要說的就是資料庫設計,要想動態載入成樹形菜單,資料庫表中就一定要設定父節點ID和自身ID。通過父節點ID判斷自身是屬於哪一級菜單,而通過自身ID判斷其對應的下一級菜單。這是資料庫設計應該注意的地方,如果沒有父節點和自身子節點,那麼就沒辦法實現動態載入樹形菜單。
動態載入樹形菜單的實現利用的zTree。這裡順便提一下,zTree的網站做的真的很好,而且各種類型的zTree做的非常完美。我就是利用zTree來實現的,只不過與之不同的是zTree實現的樹菜單也是在前台寫好的,我們要做的就是將後台用資料庫查詢到的代碼拼接成前台已經寫好的代碼格式。
這是前台寫好的樹菜單格式:
我們要做的就是將前台這種樹形菜單格式在後台拼出來,而在樹形菜單中顯示的菜單名稱是從資料庫中查詢出來的。最開始的時候嘗試拼JSON串,但是事實證明,我失敗了,拼出來的字串啟動並執行時候根本顯示不出來
拼出的JSON串跟咱們要拼接的格式是不同的,JSON串拼接出來的格式適用於結構比較簡單,這樣利用迴圈可以將需要的字串拼接出來。而我們需要的字串是需要判斷下一級是否有子節點的,這個利用JSON串我沒有實現,只能實現一級菜單,而對應的實現三級菜單我沒有拼出來。很遺憾,但是利用迴圈、遍曆和DataTable的查詢,最終實現了樹形菜單字串的拼接。下面是我實現的代碼
這個對應的實現二級菜單的拼接
public string getTree(string strTree) { string Chilstr = ""; //擷取DataTable zTreeBLL zTree = new zTreeBLL(); DataTable dt = new DataTable(); dt = zTree.QueryResource(); //查詢父節點有多少條不重複的資料 zTreeBLL zTree1 = new zTreeBLL(); DataTable dt1 = new DataTable(); dt1 = zTree1.QueryParidNum(); //父節點只能加到4 //for (int p = 0; p < Convert.ToInt32(dt1.Rows[0][0]); p++) //Convert.ToInt32強制轉換字元,把Object類型轉換成int //{ int parentId = 0; //尋找第一個父節點有多少個,即初值為0的父節點 DataRow[] rowsP = dt.Select("ParentID=" + parentId); //利用迴圈將父節點拼接起來 for (int i = 0; i < rowsP.Length; i++) { //把rowsP裡面的數值取出來 foreach (DataRow drP in rowsP) { string parName = drP["ResourceName"].ToString(); //strTree = "[{name:\""+ parName + "\""; strTree = "[{name:\"" + parName + "\""; DataRow[] rowsC = dt.Select("ParentID=" + parentId + 1); if (rowsC.Length > 0) //如果子節點不為0,則開始拼接子節點的字串 { //利用迴圈將父節點對應下的子節點串起來 foreach (DataRow drC in rowsC) { string chilName = drC["ResourceName"].ToString(); Chilstr = Chilstr + "{name:\"" + chilName + "\"}"; Chilstr = Chilstr + ","; } Chilstr = Chilstr.Remove(Chilstr.LastIndexOf(","), 1); strTree = strTree + ",children:[" + Chilstr + "]}];"; } else { strTree = strTree + "\"}];"; } } } // parentId++; //} return strTree; }
這個對應的是多級菜單的拼接
public string getTree(string strTree) { string Chilstr = ""; //擷取DataTable zTreeBLL zTree = new zTreeBLL(); DataTable dt = new DataTable(); dt = zTree.QueryResource(); //查詢父節點有多少條不重複的資料 zTreeBLL zTree1 = new zTreeBLL(); DataTable dt1 = new DataTable(); dt1 = zTree1.QueryParidNum(); //父節點只能加到4 //for (int p = 0; p < Convert.ToInt32(dt1.Rows[0][0]); p++) //Convert.ToInt32強制轉換字元,把Object類型轉換成int //{ int parentId = 0; //尋找第一個父節點有多少個,即初值為0的父節點 DataRow[] rowsP = dt.Select("ParentID=" + parentId); //利用迴圈將父節點拼接起來 for (int i = 0; i < rowsP.Length; i++) { //把rowsP裡面的數值取出來 foreach (DataRow drP in rowsP) { string parName = drP["ResourceName"].ToString(); //strTree = "[{name:\""+ parName + "\""; strTree = "[{name:\"" + parName + "\""; DataRow[] rowsC = dt.Select("ParentID=" + parentId + 1); if (rowsC.Length > 0) //如果子節點不為0,則開始拼接子節點的字串 { //利用迴圈將父節點對應下的子節點串起來 foreach (DataRow drC in rowsC) { string Threestr = ""; //判斷二級菜單下對應的ID,也就是尋找三級菜單的ParentID string chilFollow = drC["ID"].ToString(); //查詢三級菜單 DataRow[] rowsThree = dt.Select("ParentID=" + chilFollow); //判斷是否存在三級菜單 if (rowsThree.Length > 0) { foreach (DataRow drThree in rowsThree) { string ThreeName = drThree["ResourceName"].ToString(); Threestr = Threestr + "{name:\""+ThreeName+"\"}"; Threestr = Threestr + ","; } Threestr = Threestr.Remove(Threestr.LastIndexOf(","), 1); string chilName = drC["ResourceName"].ToString(); Chilstr = Chilstr + "{name:\"" + chilName + "\",children:["+Threestr+"]},"; } //如果不存在三級菜單的話直接載入二級菜單 else { string chilName = drC["ResourceName"].ToString(); Chilstr = Chilstr + "{name:\"" + chilName + "\"}"; Chilstr = Chilstr + ","; } } Chilstr = Chilstr.Remove(Chilstr.LastIndexOf(","), 1); strTree = strTree + ",children:[" + Chilstr + "]}];"; } else { strTree = strTree + "\"}];"; } } } return strTree; }
最終實現的效果
其實實現這個例子的方法還有很多種,比如說遞迴。雖然JSON串沒有拼接成功,但是我覺得JSON串是可以實現的。只是鑒於個人能力的緣故最終沒有拼接成功。動態載入樹形菜單終於實現的,但是還有很多需要改進的地方,比如如何將這個方法封裝起來,以至於可以無限的調用沒有缺陷等,這是下一步值得繼續探討的問題。