基於MVC4+EasyUI的Web開發框架經驗總結(3)- 使用Json實體類構建菜單數據

最近花了很多時間在重構和進一步提煉個人Web開發框架上,力求在用戶體驗和界面設計方面,和Winform開發框架保持一致,而在Web上,我主要採用EasyUI的前端界面處理技術,走MVC的技術路線,在重構完善過程當中,不少細節花費很多時間進行研究和提煉,一步步走過來,也積累了很多經驗,本系列將主要介紹我在進一步完善個人Web框架基礎上積累的經驗進行分享,本隨筆主要介紹使用如何使用Json實體類構建菜單數據,而後在主界面中進行使用。javascript

 菜單的界面效果以下所示,菜單分爲一級菜單、二級菜單、三級菜單,他們各自在位置上是不一樣的定義,這個界面佈局規定三級菜單就是最小的菜單節點了,也就是葉子節點。html

要實現以上的菜單,須要把菜單定義成相關的Json數據,而後經過腳本把它們添加到界面裏面去,以下數據和腳本就是定義相關的菜單數據的。前端

    <script type="text/javascript">
        var _menus = {
            "default": [
                {
                    "menuid": "1", "icon": "icon-computer", "menuname": "權限管理",
                    "menus": [
                              { "menuid": "13", "menuname": "用戶管理", "icon": "icon-user", "url": "/User/Index" },
                              { "menuid": "14", "menuname": "組織機構管理", "icon": "icon-organ", "url": "/OU/Index" },
                              { "menuid": "15", "menuname": "角色管理", "icon": "icon-group-key", "url": "/Role/Index" },
                              { "menuid": "16", "menuname": "功能管理", "icon": "icon-key", "url": "/Function/Index" },
                              { "menuid": "17", "menuname": "登錄日誌", "icon": "icon-view", "url": "/LoginLog/Index" }
                    ]
                },
               {
                   "menuid": "2", "icon": "icon-user", "menuname": "其餘管理",
                   "menus": [{ "menuid": "21", "menuname": "修改密碼", "icon": "icon-lock", "url": "javascript:ShowPasswordDialog()" }
                   ]
               }
            ],
            "point": [
                {
                    "menuid": "3", "icon": "icon-computer", "menuname": "事務中心",
                    "menus": [
                              { "menuid": "33", "menuname": "測試菜單1", "icon": "icon-user", "url": "../Commonpage/building.htm" },
                              { "menuid": "34", "menuname": "測試菜單2", "icon": "icon-organ", "url": "../Commonpage/building.htm" },
                              { "menuid": "35", "menuname": "測試菜單3", "icon": "icon-group-key", "url": "../Commonpage/building.htm" },
                              { "menuid": "36", "menuname": "測試菜單4", "icon": "icon-key", "url": "../Commonpage/building.htm" }
                    ]
                },
                {
                    "menuid": "4", "icon": "icon-user", "menuname": "其餘菜單",
                    "menus": [{ "menuid": "41", "menuname": "測試菜單5", "icon": "icon-lock", "url": "../Commonpage/building.htm" }]
                }
            ]
        };

        function showSubMenu(url, title, menuCategory, defaultIcon) {
            if (defaultIcon == null || defaultIcon == "") {
                defaultIcon = "icon-table";
            }
            addTab(title, url, "icon " + defaultIcon);
            Clearnav();
            if (menuCategory != "") {
                addNav(_menus[menuCategory]);
            }
        }
    </script>

從上面的菜單Json數據來看,它是一個字典的Json數據列表,在Web界面上,經過下面的代碼能夠展開上面Json定義的二級菜單。java

<li><a href="#" onclick="showSubMenu('/User/Index', '用戶管理', 'default')">權限管理</a></li>

雖然上面的定義的數據可以解決菜單的顯示問題,可是對於咱們須要動態控制的菜單,顯然作不到,所以須要把上面的json數據,經過菜單控制器進行動態生成才能夠,而後在腳本里面經過Jquery的方式獲取Json數據,以下所示。node

        var _menus = {};
        //同步獲取
        $.ajax({
            type: 'GET',
            url: '/Menu/GetMenuData?r=' + Math.random(),
            async: false,//同步
            dataType: 'json',
            success: function (json) {
                _menus = json;
            },
            error: function (xhr, status, error) {
                alert("操做失敗"); //xhr.responseText
            }
        });

上面的GetMenuData方法,經過後臺的控制器進行動態生成的,它的代碼以下所示ajax

        /// <summary>
        /// 獲取樹形展現數據
        /// </summary>
        /// <returns></returns>
        public ActionResult GetMenuData()
        {
            string json = GetTreeJson("-1", "", "");
            json = json.Trim(',');
            return Content(string.Format("[{0}]", json));
        }

        /// <summary>
        /// 遞歸獲取樹形信息
        /// </summary>
        /// <returns></returns>
        private string GetTreeJson(string PID, string folderIcon, string leafIcon)
        {
            string condition = string.Format("PID='{0}' ", PID);
            List<MenuInfo> nodeList = BLLFactory<Menu>.Instance.Find(condition);
            StringBuilder content = new StringBuilder();
            foreach (MenuInfo model in nodeList)
            {
                string ParentID = (model.PID == "-1" ? "0" : model.PID);
                string subMenu = this.GetTreeJson(model.ID, folderIcon, leafIcon);
                string parentMenu = string.Format("{{ \"id\":\"{0}\", \"pId\":\"{1}\", \"name\":\"{2}\" ", model.ID, ParentID, model.Name);
                if (string.IsNullOrEmpty(subMenu))
                {
                    if (!string.IsNullOrEmpty(leafIcon))
                    {
                        parentMenu += string.Format(",\"icon\":\"{0}\" }},", leafIcon);
                    }
                    else
                    {
                        parentMenu += "},";
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(folderIcon))
                    {
                        parentMenu += string.Format(",\"icon\":\"{0}\" }},", folderIcon);
                    }
                    else
                    {
                        parentMenu += "},";
                    }
                }

                content.AppendLine(parentMenu.Trim());
                content.AppendLine(subMenu.Trim());
            }
            return content.ToString().Trim();
        }

不過對於上面的代碼,我以爲雖然能解決問題,可以正確生成相關的Json代碼,可是感受不夠優雅,我不喜歡使用拼湊方法構建數據。json

前面看了Menu的Json腳本,我說過他是一個字典類型的Json數據格式,那麼咱們是否能夠經過字典和實體信息來承載,而後直接經過ToJson方法出來呢?答案是能夠的。框架

        /// <summary>
        /// 獲取菜單的樹形展現數據
        /// </summary>
        /// <returns></returns>
        public ActionResult GetMenuData()
        {
            Dictionary<string, List<MenuData>> dict = new Dictionary<string, List<MenuData>>();
                                                     
            List<MenuInfo> list = BLLFactory<Menu>.Instance.GetTopMenu(MyConstants.SystemType);
            int i = 0;
            foreach (MenuInfo info in list)
            {
                if (!HasFunction(info.FunctionId))
                {
                    continue;
                }              
                List<MenuData> treeList = new List<MenuData>();
                List<MenuNodeInfo> nodeList = BLLFactory<Menu>.Instance.GetTreeByID(info.ID);
                foreach (MenuNodeInfo nodeInfo in nodeList)
                {
                    if (!HasFunction(nodeInfo.FunctionId))
                    {
                        continue;
                    }                                                                                                                                                                       
                    MenuData menuData = new MenuData(nodeInfo.ID, nodeInfo.Name, string.IsNullOrEmpty(nodeInfo.WebIcon) ? "icon-computer" : nodeInfo.WebIcon);
                    foreach (MenuNodeInfo subNodeInfo in nodeInfo.Children)
                    {
                        if (!HasFunction(subNodeInfo.FunctionId))
                        {
                            continue;
                        }
                        string icon = string.IsNullOrEmpty(subNodeInfo.WebIcon) ? "icon-organ" : subNodeInfo.WebIcon;
                        menuData.menus.Add(new MenuData(subNodeInfo.ID, subNodeInfo.Name, icon, subNodeInfo.Url));
                    }
                    treeList.Add(menuData);
                }

                //添加到字典裏面,若是是第一個,默認用default名稱
                string dictName = (i++ == 0) ? "default" : info.ID;
                dict.Add(dictName, treeList);
            }

            string content = ToJson(dict);
            return Content(content.Trim(','));
        }

上面的代碼,經過MenuData的對象數據,來承載相關的菜單信息,而後把它添加到字典Dictionary<string, List<MenuData>> dict 裏面就能夠了,這樣的代碼,沒有那麼多拼湊出來的感受,是否是很好看呢?把對象轉換爲Json數據,直接經過ToJson就能夠解決了,很簡單吧。dom

而菜單的權限控制,就是經過集合權限管理進行判斷,父菜單若是沒有權限,就直接跳過,不在繼續生成下面的子菜單,權限判斷的以下所示。async

if (!HasFunction(info.FunctionId))
{
       continue;
 } 

固然,在界面上展開二級菜單的操做界面,也應該經過腳本動態進行生成的,這樣才能作到全部的內容動態構建。

        <ul class="navigation" style="display:block">
            @Html.Raw(@ViewBag.HeaderScript)</ul>

上面使用ViewBag對象進行傳遞腳本內容到界面上,其實後臺生成的操做,是一行HTML代碼就是了,代碼相似下面的內容。

<li><a href="#" onclick="showSubMenu('/User/Index', '用戶管理', 'default')">權限管理</a></li>

最後出來的效果,就是博客開始介紹的界面截圖,沒有任何變化,可是代碼咱們已經通過了幾步的優化整理,看起來很清爽,更能實現動態變化了。

 

有空能夠回顧下其餘兩篇的經驗總結內容:

基於MVC4+EasyUI的Web開發框架的系列文章:

基於MVC4+EasyUI的Web開發框架造成之旅--整體介紹

基於MVC4+EasyUI的Web開發框架造成之旅--MVC控制器的設計

基於MVC4+EasyUI的Web開發框架造成之旅--界面控件的使用

基於MVC4+EasyUI的Web開發框架造成之旅--附件上傳組件uploadify的使用

基於MVC4+EasyUI的Web開發框架造成之旅--框架整體界面介紹

基於MVC4+EasyUI的Web開發框架造成之旅--基類控制器CRUD的操做

基於MVC4+EasyUI的Web開發框架造成之旅--權限控制

基於MVC4+EasyUI的Web開發框架經驗總結(1)-利用jQuery Tags Input 插件顯示選擇記錄

基於MVC4+EasyUI的Web開發框架經驗總結(2)- 使用EasyUI的樹控件構建Web界面

基於MVC4+EasyUI的Web開發框架經驗總結(3)- 使用Json實體類構建菜單數據

基於MVC4+EasyUI的Web開發框架經驗總結(4)--使用圖表控件Highcharts

基於MVC4+EasyUI的Web開發框架經驗總結(5)--使用HTML編輯控件CKEditor和CKFinder

基於MVC4+EasyUI的Web開發框架經驗總結(6)--在頁面中應用下拉列表的處理

基於MVC4+EasyUI的Web開發框架經驗總結(7)--實現省份、城市、行政區三者聯動

基於MVC4+EasyUI的Web開發框架經驗總結(8)--實現Office文檔的預覽

基於MVC4+EasyUI的Web開發框架經驗總結(9)--在Datagrid裏面實現外鍵字段的轉義操做

基於MVC4+EasyUI的Web開發框架經驗總結(10)--在Web界面上實現數據的導入和導出

基於MVC4+EasyUI的Web開發框架經驗總結(11)--使用Bundles處理簡化頁面代碼

基於MVC4+EasyUI的Web開發框架經驗總結(12)--利用Jquery處理數據交互的幾種方式

基於MVC4+EasyUI的Web開發框架經驗總結(13)--DataGrid控件實現自動適應寬帶高度

基於MVC4+EasyUI的Web開發框架經驗總結(14)--自動生成圖標樣式文件和圖標的選擇操做

相關文章
相關標籤/搜索