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

http://www.cnblogs.com/wuhuacong/p/3669575.htmljavascript

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

在不少界面設計上,咱們可能都須要引入樹列表控件,這個控件能夠用zTree來實現,也能夠用EasyUI的內置樹控件進行展現,因爲歷史緣由,我原來傾向於使用zTree,最新把它所有修改成EasyUI的樹控件,並進行了完善優化,發現代碼更加簡潔明快,很是不錯。前端

一、在界面上使用EasyUI的樹控件

通常狀況下,使用EasyUI的樹控件,代碼很簡單,腳本代碼以下所示,主要就是經過調用url來得到Json數據,而後就能夠顯示了,經過onClick就能夠響應用戶單擊節點的操做,每一個節點有id, text, iconCls, checked,state,children等屬性。java

1)樹控件的Json數據綁定node

複製代碼
            $('#treeDept').tree({
                url: '/User/GetMyDeptTreeJson?userId=@Session["UserId"]',
                onClick: function (node) {
                    loadData(node.id);
                }
            });
複製代碼

2)樹控件的摺疊和展開數據庫

樹控件的展開和摺疊,能夠經過定義兩個通用的腳本進行處理,以下所示。json

複製代碼
        function expandAll(treeName) {
            var node = $('#' + treeName).tree('getSelected');
            if (node) {
                $('#' + treeName).tree('expandAll', node.target);
            }
            else {
                $('#' + treeName).tree('expandAll');
            }
        }
        function collapseAll(treeName) {
            var node = $('#' + treeName).tree('getSelected');
            if (node) {
                $('#' + treeName).tree('collapseAll', node.target);
            }
            else {
                $('#' + treeName).tree('collapseAll');
            }
        }
複製代碼

而後,在頁面加載完畢後,綁定指定的按鈕控件就能夠了嗎,以下代碼所示。框架

複製代碼
        //初始化對象
        $(document).ready(function () {
            //初始化機構分類
            initOUCategorys();

            //機構基礎信息
            initDeptTreeview();
            $("#deptExpand").bind("click", function () {
                expandAll("treeDept");
            });
            $("#deptCollapse").bind("click", function () {
                collapseAll("treeDept");
            });                       

            $("#loading").center(); //loading的圖片顯示居中
        });
複製代碼

3)樹控件的複選框顯示函數

樹控件默認是沒有複選框的,它能夠經過屬性checkbox設置讓它進行展現的,以下代碼是我項目裏面的代碼。優化

其中cascadeCheck是否讓樹控件級聯的,默認是級聯,也就是隻要父控件被選中,全部其子控件都會被選中,咱們能夠設置它爲false,讓它不級聯,這樣在不少狀況下是須要的。

複製代碼
            $('#treeFunctionView').tree({
                checkbox: true,
                cascadeCheck: false,
                url: '/Function/GetRoleFunctionByUser?userId=@Session["UserId"]',
                onClick: function (node) {
                    //
                }
            });
複製代碼

4)樹控件的全選和全不選擇

這個所有不選的特性,我找了不少文章,都沒有找到,其實後來才發現,咱們對樹的節點理解有誤差,認識到後,實現起來也很容易。

如取消所有節點的選中狀態,代碼以下所示。它的方法getChecked是返回全部的節點,而不是一個節點。它們把所有選中的節點放到一個結合裏面,不像Winform裏面,樹節點須要遞歸查詢,這裏只須要一個for循環就能夠展開了,我這裏把全部勾選的節點,設置爲非勾選狀態就能夠實現取消所有樹節點勾選狀態了。

複製代碼
        function unCheckTree(tree) {
            var nodes = $('#' + tree).tree('getChecked');
            if (nodes) {
                for (var i = 0; i < nodes.length; i++) {
                    $('#' + tree).tree('uncheck', nodes[i].target);
                }
            }
        }
複製代碼

咱們知道,不少樹控件,爲了方便操做,都提供了一個全選或者所有不選的操做,這個在EasyUI的樹控件裏面,也是很容易實現的。這裏的getChildren和上面的意思相似,也是返回全部的子節點,不須要在進行遞歸,用一個for循環就能夠遍歷所有節點和其下面的多級子節點了。也就是說,它是一個二維的數據,不用遞歸查詢。

複製代碼
        function checkAllTree(tree, checked) {
            var children = $('#' + tree).tree('getChildren');
            for (var i = 0; i < children.length; i++) {
                if (checked) {
                    $('#' + tree).tree('check', children[i].target);
                } else {
                    $('#' + tree).tree('uncheck', children[i].target);
                }
            }
        }
複製代碼

 

5)下拉列表的樹控件初始化

除了普通的樹列表,還有一種比較特殊的樹控件,就是在ComboTree,也就是在下拉列表中集成樹控件,它的操做和普通的樹控件差很少,不少事件屬性都同樣,它的使用代碼以下所示。

複製代碼
        //初始化公司
        function initCompany() {
            $('#txtCompany_ID').combotree({
                url: '/User/GetMyCompanyTreeJson?userId=@Session["UserId"]',
                valueField: 'id',
                textField: 'text',
                required: true,
                onClick: function (node) {
                    //
                }
            });
        }
複製代碼

 

二、樹控件的優化

1)普通的Json數據生成

前面說了,咱們爲了方便,通常使用Json數據和javascript打交道,而EasyUI的樹控件支持很好地的Json連接綁定,所以咱們只須要在對應的控制器裏面實現json數據的生成便可,若是是一開始想要肯定的Json數據,通常也是經過手工生成的居多,以下代碼所示。

複製代碼
        public ActionResult GetTreeJson()
        {
            string folder = "/Content/JqueryEasyUI/themes/icons/customed/" + "organ.png";
            string leaf = "/Content/JqueryEasyUI/themes/icons/customed/" + "organ.png";
            string json = GetTreeJson(-1, folder, leaf);
            json = json.Trim(',');
            return Content(string.Format("[{0}]", json));
        }

        /// <summary>
        /// 遞歸獲取樹形信息
        /// </summary>
        /// <param name="PID"></param>
        /// <returns></returns>
        private string GetTreeJson(int PID, string folderIcon, string leafIcon)
        {
            string condition = string.Format("PID={0}", PID);
            List<OUInfo> nodeList = BLLFactory<OU>.Instance.Find(condition);
            StringBuilder content = new StringBuilder();
            foreach (OUInfo model in nodeList)
            {
                int ParentID = (model.PID == -1 ? 0 : model.PID);
                //string tempMenu = string.Format("{{ id:{0}, pId:{1}, name:\"{2}\",icon:\"{3}\" }},", model.ID, ParentID, model.Name, imgsrc);
                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數據,可是感受部分硬編碼,湊出來的數據,始終感受不太理想,若是咱們要簡化,該如何操做呢?

 

2)簡潔美觀的Json數據生成

本小節繼續上面的議題,看如何簡化json的生成,由於咱們須要不少這樣的json操做,若是採用上面的方法,我感受很容易出錯,並且也不太美觀。爲了解決這個問題,咱們能夠經過定義一個json數據的實體類,用來承載相關的信息,以下定義所示。

複製代碼
    /// <summary>
    /// 定義EasyUI樹的相關數據,方便控制器生成Json數據進行傳遞
    /// </summary>
    [DataContract]
    [Serializable]
    public class EasyTreeData
    {
        /// <summary>
        /// ID
        /// </summary>
        [DataMember]
        public string id { get; set; }

        /// <summary>
        /// 節點名稱
        /// </summary>
        [DataMember]
        public string text { get; set; }
        
        /// <summary>
        /// 是否展開
        /// </summary>
        [DataMember]
        public string state  { get; set; }

        /// <summary>
        /// 圖標樣式
        /// </summary>
        [DataMember]
        public string iconCls { get; set; }


        /// <summary>
        /// 子節點集合
        /// </summary>
        [DataMember]
        public List<EasyTreeData> children { get; set; }
        
        /// <summary>
        /// 默認構造函數
        /// </summary>
        public EasyTreeData() 
        {
            this.children = new List<EasyTreeData>();
            this.state = "open";
        }

        /// <summary>
        /// 經常使用構造函數
        /// </summary>
        public EasyTreeData(string id, string text, string iconCls = "", string state = "open")
            : this()
        {
            this.id = id;
            this.text = text;
            this.state = state;
            this.iconCls = iconCls;
        }

        /// <summary>
        /// 經常使用構造函數
        /// </summary>
        public EasyTreeData(int id, string text, string iconCls = "", string state = "open")
            : this()
        {
            this.id = id.ToString();
            this.text = text;
            this.state = state;
            this.iconCls = iconCls;
        }
    }
複製代碼

而後,咱們在須要生成Json數據的地方,使用這個實體類進行承載,而後把它列表生成Json就能夠了,很簡單了,呵呵。

複製代碼
        /// <summary>
        /// 根據用戶獲取對應人員層次的樹Json
        /// </summary>
        /// <param name="deptId">用戶所在部門</param>
        /// <returns></returns>
        public ActionResult GetUserTreeJson(int deptId)
        {
            List<EasyTreeData> treeList = new List<EasyTreeData>();
            treeList.Insert(0, new EasyTreeData(-1, "無"));

            List<UserInfo> list = BLLFactory<User>.Instance.FindByDept(deptId);
            foreach (UserInfo info in list)
            {
                treeList.Add(new EasyTreeData(info.ID, info.FullName, "icon-user"));
            }

            string json = ToJson(treeList);
            return Content(json);
        }
複製代碼

若是須要遞歸的操做,同樣的方式處理就能夠了。

複製代碼
        /// <summary>
        /// 獲取用戶的部門樹結構(分級須要)
        /// </summary>
        /// <param name="userId">用戶ID</param>
        /// <returns></returns>
        public ActionResult GetMyDeptTreeJson(int userId)
        {
            StringBuilder content = new StringBuilder();
            UserInfo userInfo = BLLFactory<User>.Instance.FindByID(userId);
            if (userInfo != null)
            {
                OUInfo groupInfo = GetMyTopGroup(userInfo);
                if (groupInfo != null)
                {
                    List<OUNodeInfo> list = BLLFactory<OU>.Instance.GetTreeByID(groupInfo.ID);

                    EasyTreeData treeData = new EasyTreeData(groupInfo.ID, groupInfo.Name, GetIconcls(groupInfo.Category));
                    GetTreeDataWithOUNode(list, treeData);

                    content.Append(base.ToJson(treeData));
                }
            }
            string json = string.Format("[{0}]", content.ToString().Trim(','));
            return Content(json);
        }
複製代碼

上面使用EasyTreeData來承載數據,而後構建列表,其自己就是一個多層級的樹對象,而後一個ToJson的方法就能夠把列表對象完美轉換爲Jason數據了。

這裏的ToJson,主要就是調用JavaScriptSerializer 對象進行的操做,以下所示。

複製代碼
        /// <summary>
        /// 把對象爲json字符串
        /// </summary>
        /// <param name="obj">待序列號對象</param>
        /// <returns></returns>
        protected string ToJson(object obj)
        {
            string jsonData = (new JavaScriptSerializer()).Serialize(obj);
            return jsonData;
        }
複製代碼

 

三、樹控件效果展現

在介紹如何使用它以後,咱們來看看我幾個場景中使用樹控件進行的展現效果,方便咱們加深上面EasyUI樹控件使用的瞭解。

1)組織機構列表以下所示:

2)角色樹列表展現

 

3)功能樹列表展現

4)菜單樹列表展現

5)登錄日誌樹列表展現

6)下拉列表樹展現

  

    

相關文章
相關標籤/搜索