Tree资源树的实战研究

背景简介:

最近小编在做项目的时候,遇到了一个动态添加资源树的问题,经过几番实践,终于实现了最终的结果,下面我会将自己的经历一点点抛给大家,希望读者尽情享受这顿盛宴。

这里,我们将实现如下图效果(功能介绍,通过选择年份显示左侧资源树,通过单击资源树在右侧表格中显示该指标中的档次信息):

一、自己动手js拼接树实践

HTML中就一句接收代码,Controller中将查询到的信息转换成json反到js中就可以了,这里主要是通过js控制树的一个拼接过程,如下代码:

<span style="font-family:KaiTi_GB2312;font-size:18px;">-
//通过年份查询定性指标,返回树-马康-2016-3-25 22:22:20
function QueryUnitObjectByYearType() {
    var nodeChild = document.getElementById("NodeChild");
    //获取下拉框中的年份
    var CheckYear = $('#CheckYear').combobox('getValue');

    //查询资源信息
    $.post("/SetQualitativeTargetLevel/QueryQualitativeTargetByYear?CheckYear=" + CheckYear, {}, function (data) {
        //添加的时候先清除div中的数据
        $("#tree").empty();
        //将得到的集合按照指标类型去重放到res集合中
        var res = [];
        var json = {};
        for (var i = 0; i < data.length; i++) {
            if (!json[data[i].DictionaryName]) {
                res.push(data[i].DictionaryName);
                json[data[i].DictionaryName] = 1;
            }
        }
        //遍历去重之后的集合,显示到树的div中
        $.each(res, function (i, item) {
            if (item == "班子") {
                $("#tree").append("<ul id='UnittreeTarget' ><li><span>" + item + "</span></li></ul>");
            }
            else {
                $("#tree").append("<ul id='CardrestreeTarget' ><li><span>" + item + "</span></li></ul>");
            }
        });
        //遍历向div中添加查询到的指标信息
        $.each(data, function (i, item) {
            if (item.DictionaryName == "班子") {
                $("#UnittreeTarget").append("<ul><li><span>" + item.QualitativeTargetName + "</span></li></ul>");
            }
            else {
                $("#CardrestreeTarget").append("<ul><li><span>" + item.QualitativeTargetName + "</span></li></ul>");
            }
        });
    });
}
-</span>

最终实现的效果图如下(这里只是将资源以一个树的结构显示出来了,并没有实现单击查询的功能):

二、模仿老系统通过Controller中json转换拼接成树形结构的实战

这种方法HTML中也只有一句接收代码,js中就一句传递代码,主要代码在Controller中来实现的,代码如下:

调用后台数据的方法:

<span style="font-family:KaiTi_GB2312;font-size:18px;">-
#region QueryQualitativeTargetByYear 根据年份分页查询定性指标-马康-2016-3-4 0:17:45
        /// <summary>
        /// 根据年份分页查询定性指标-马康-2016-3-4 0:17:45
        /// </summary>
        /// <returns></returns>
        public string QueryQualitativeTargetByYear()
        {

            //实例化返回数据的载体-AllQuantifyResultInputViewModel(实例化伟涛写的ViewModel)
            List<SetQualitativeTargetViewModel> SetQualitativeTargetViewModel = new List<SetQualitativeTargetViewModel>();

            //获取界面传过来的考核年份
            string CheckYear1 = Request["CheckYear"];
            //将考核年份转换为int类型
            int CheckYear = Convert.ToInt32(CheckYear1);

            //通过考核年份调用服务端查询定量考核指标名称的方法(调用伟涛写的查询方法)
            SetQualitativeTargetViewModel = ISetQualitativeTarget.QueryQualitativeTargetByYear1(CheckYear);

            //将查询到的集合按照类型ID排序
            var str = from p in SetQualitativeTargetViewModel orderby p.DictionaryID select p;

            //实例化一个datatable
            DataTable dtTreeInfo = new DataTable();

            //添加列头
            dtTreeInfo.Columns.Add("id");
            dtTreeInfo.Columns.Add("name");
            //定义变量
            string DictionaryName = "";

            foreach (var item in str)
            {
                //判断去重
                if (DictionaryName != item.DictionaryName)
                {
                    //将不重复的值放到datatable中
                    DictionaryName = item.DictionaryName;
                    DataRow data = dtTreeInfo.NewRow();
                    data["id"] = item.DictionaryID;
                    data["name"] = item.DictionaryName;
                    dtTreeInfo.Rows.Add(data);
                }
            }

            string strJson = getJson(dtTreeInfo, SetQualitativeTargetViewModel);
            //将查询到的数据转换为Json返回到界面上
            return strJson;

        }
        #endregion
-</span>

转换树形js的方法:

<span style="font-family:KaiTi_GB2312;font-size:18px;">-
 /// <summary>
        /// 节点树的组合-父节点树的遍历-马康-2016-4-5 14:00:35
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public string getJson(DataTable dt, List<SetQualitativeTargetViewModel> SetQualitativeTargetViewModel)
        {
            //实例化承载字符串的json
            StringBuilder json = new StringBuilder();
            json.Append("[");

            foreach (DataRow dr in dt.Rows)
            {
                //将传进来的dt转换成只有子节点的dt
                DataTable dtChildren = new DataTable();
                //添加列头
                dtChildren.Columns.Add("id");
                dtChildren.Columns.Add("name");

                json.Append("{\"id\":" + dr["id"].ToString());
                json.Append(",\"text\":\"" + dr["name"].ToString() + "\"");
                json.Append(",\"state\":\"closed\"");

                //按照类型查询相应的定性指标
                var str = from m in SetQualitativeTargetViewModel where (m.DictionaryID.ToString() == dr["id"].ToString()) select m;
                //通过循环将查询到的定性指标存放到DataTable中
                foreach (var item in str)
                {
                    //实例化一个DataRow
                    DataRow data = dtChildren.NewRow();
                    //向DataRow中添加列头
                    data["id"] = item.QualitativeTargetID;
                    data["name"] = item.QualitativeTargetName;
                    //将dataRow中的数据添加到DataTable中
                    dtChildren.Rows.Add(data);
                }

                //调用D层方法获取dataTable
                if (dtChildren.Rows.Count == 0)
                {
                    return null;
                }
                //添加树字节点的json
                if (dt != null && dt.Rows.Count > 0)
                {
                    json.Append(",\"children\":[");
                    //调用将子节点转换成json树结构的方法
                    json.Append(DataTable2Json(dtChildren, dr["id"].ToString()));
                    json.Append("]");
                }
                json.Append("},");
            }
            if (dt.Rows.Count > 0)
            {
                json.Remove(json.Length - 1, 1);
            }
            //添加最后的]
            json.Append("]");
            //返回json
            return json.ToString();
        }

        #region DataTable2Json 子节点树的遍历-马康-2016-4-5 14:04:36
        /// <summary>
        /// DataTable2Json 子节点树的遍历
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string DataTable2Json(DataTable dt, string pid)
        {
            //实例化json
            StringBuilder jsonBuilder = new StringBuilder();
            //循环,将数据转换成树结构的json
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                jsonBuilder.Append("{");
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    //实例化并承接表示GUID
                    Guid id = new Guid(pid);
                    jsonBuilder.Append("\"");
                    //将列头字符转换成小写字母
                    dt.Columns[j].ColumnName = dt.Columns[j].ColumnName.ToLower();
                    //将列头为name转换成text
                    if (dt.Columns[j].ColumnName == "name") dt.Columns[j].ColumnName = "text";
                    //添加
                    jsonBuilder.Append(dt.Columns[j].ColumnName);
                    jsonBuilder.Append("\":\"" + dt.Rows[i][j].ToString() + "\",");
                }

                if (dt.Columns.Count > 0)
                {
                    jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
                }
                jsonBuilder.Append("},");
            }
            if (dt.Rows.Count > 0)
            {
                jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
            }
            return jsonBuilder.ToString();
        }
        #endregion
-</span>

这个实现起来比较麻烦,其中涉及了好多拼接转换,真正实现不建议用这样的方式,可以通过这个方式来锻炼一下自己的逻辑能力还是很不错的O(∩_∩)O~

三、使用Easyui通过js控制的实战

小编这里实现的时候用的是zTree,下面是需要注意的地方以及对应的代码:

HTML:树Easyui的引用,承载树的代码

<span style="font-family:KaiTi_GB2312;font-size:18px;">-
<script src="../../Content/zTree3.5/js/jquery.ztree.all-3.5.min.js"></script>
    <script src="../../Content/zTree3.5/js/jquery.ztree.core-3.5.min.js"></script>
    <script src="../../Content/zTree3.5/js/jquery.ztree.excheck-3.5.js"></script>
    <link href="../../Content/zTree3.5/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />

 @*树的加载*@
        <div id="tree" class="easyui-panel" data-options="region:'west',split:true" title="定性指标体系" style="width: 200px;">
        </div>
-</span>

js:资源树的查询方法,资源树的单击获取资源树节点ID之后查询内容的方法

<span style="font-family:KaiTi_GB2312;font-size:18px;">-
//通过年份查询定性指标,返回树-马康-2016-3-25 22:22:20
function QueryUnitObjectByYearType() {
    //获取下拉框中的年份
    var CheckYear = $('#CheckYear').combobox('getValue');

    //加载为分配角色树
    var tree = {
        /**
        * 所有的初始化的操作
        */
        setting:
        {
            //定义单击树节点的事件(js中必须有zTreeOnClick这个function)
            callback: {
                onClick: zTreeOnClick
            },
            //树的格式
            check: {
                enable: false,
                chkboxType: { "Y": "", "N": "" }
            },
            //树的数据
            data:
            {
                key:
                {
                    //要显示的字段
                    name: "QualitativeTargetName"
                },
                simpleData:
                {
                    enable: true,   //是否显示树形结构
                    //子节点
                    idKey: "QualitativeTargetID",
                    //父节点
                    pIdKey: "DictionaryID",
                    rootPId: "0"
                }
            },
            open:true
        }
    };

    //post提交,将查询条件传到controller中,并且接受controller返回回来的数据
    $.post("/SetQualitativeTargetLevel/QueryQualitativeTargetByYear?CheckYear=" + CheckYear, {}, function (result) {
        //jquery中的zTree方法,放置的容器($("#tree")),配置( tree.setting),数据(result)
        $.fn.zTree.init($("#tree"), tree.setting, result);
    });
}

//全局变量,为了单击的时候将单击的指标ID存入其中,添加的时候使用
var OnclickQualitativeTargetID = "";
//树的单击事件-根据年份和定性指标ID查询定性档次-马康-2016-4-6 22:03:34
function zTreeOnClick(e, treeId, treeNode) {
    //获取下拉框中的年份
    var CheckYear = $('#CheckYear').combobox('getValue');

    //获取单击的指标ID
    OnclickQualitativeTargetID = treeNode.QualitativeTargetID;

    //定性指标基础信息上面显示单击的定性指标名称
    document.getElementById("NodeChild").innerHTML = treeNode.QualitativeTargetName;

    //通过年份和指标Id查询未录入成绩的考核对象
    $('#dg').datagrid({
        url: '/SetQualitativeTargetLevel/QueryQualitativeTargetLevelByTargetYear?CheckYear=' + CheckYear + '&QualitativeTargetID=' + OnclickQualitativeTargetID,
        //title: '演示表格使用',
        width: "100%",
        striped: true, //行背景交换
        fitColumns: true,
        idField: 'ID',
        loadMsg: '正在加载用户的信息...',
        pagination: true,
        singleSelect: false,

        pageList: [10, 20, 30, 40, 50],
        pageSize: 10,
        pageNumber: 1,
        queryParams: {
            searchName: $("#searchName").val()
        },

    }).datagrid("reload");
}
-</span>

Controller:资源的汇集,这里需要特别注意的是父节点需要当成一行数据和子节点放在一起(可以通过数据库设计到一起,也可以通过代码转换拼接到一起)小编这里是在Controller中进行的拼接

<span style="font-family:KaiTi_GB2312;font-size:18px;">-
        #region QueryQualitativeTargetByYear 根据年份分页查询定性指标-马康-2016-3-4 0:17:45
        /// <summary>
        /// 根据年份分页查询定性指标-马康-2016-3-4 0:17:45
        /// </summary>
        /// <returns></returns>
        public ActionResult QueryQualitativeTargetByYear()
        {

            //实例化返回数据的载体-AllQuantifyResultInputViewModel(实例化伟涛写的ViewModel)
            List<SetQualitativeTargetViewModel> listSetQualitativeTargetVM = new List<SetQualitativeTargetViewModel>();

            //获取界面传过来的考核年份
            string CheckYear1 = Request["CheckYear"];
            //将考核年份转换为int类型
            int CheckYear = Convert.ToInt32(CheckYear1);

            //通过考核年份调用服务端查询定量考核指标名称的方法(调用伟涛写的查询方法)
            listSetQualitativeTargetVM= ISetQualitativeTarget.QueryQualitativeTargetByYear1(CheckYear);

            //用linq语句将查询到的集合按照类型ID排序,用这个排序的集合进行循环
            //(因为需要往listSetQualitativeTargetVM集合中添加数据,用listSetQualitativeTargetVM集合循环就会出错)
            var str = from p in listSetQualitativeTargetVM orderby p.DictionaryID select p;

            //定义一个变量来存放名称,去重的时候用到
            string DictionaryName = "";
            foreach (var item in str)
            {
                //实例化一个实体
                SetQualitativeTargetViewModel enSetQualitativeTargetVM = new SetQualitativeTargetViewModel();
                //判断去重
                if (DictionaryName != item.DictionaryName)
                {
                    //将不重复的值放到listSetQualitativeTargetVM集合中当成一条数据
                    DictionaryName = item.DictionaryName;
                    //将类型ID放入指标ID中
                    enSetQualitativeTargetVM.QualitativeTargetID = item.DictionaryID;
                    //将类型名称放入指标名称中
                    enSetQualitativeTargetVM.QualitativeTargetName = item.DictionaryName;
                    //将实体添加到list集合中
                    listSetQualitativeTargetVM.Add(enSetQualitativeTargetVM);
                }
            }

            //将查询到的数据转换为Json返回到界面上
            return Json(listSetQualitativeTargetVM, JsonRequestBehavior.AllowGet);
        }
        #endregion
-</span>

表结构:这里只需要用到下图红色字体的信息(类型名称是通过类型ID查询得到的)

四、总结收获

1、非常感谢在小编成长路上给予帮助与指导的师哥师姐

2、遇到问题先寻找思路很重要

3、有了思路就马上去践行,切记不要一直思考用那种方法更合适

4、践行之后的总结很重要,将自己开始到最终的思路缕一遍

5、搜查自己在实践过程中的局限性,寻求相应的解决办法

6、不要太在意自己的初速度,要在后天培养自己的加速度(踏实走好每一就是一个培养加速度的践行)

7、很长时间没有成效不要气馁焦躁,积极主动寻求帮助,站在巨人肩膀上

8、始终相信自己一定可以揭取最后的桂冠GO GO GO O(∩_∩)O~

时间: 2024-08-24 15:36:58

Tree资源树的实战研究的相关文章

HDU 4718 The LCIS on the Tree(树链剖分)

Problem Description For a sequence S1, S2, ... , SN, and a pair of integers (i, j), if 1 <= i <= j <= N and Si < Si+1 < Si+2 < ... < Sj-1 < Sj , then the sequence Si, Si+1, ... , Sj is a CIS(Continuous Increasing Subsequence). The

HDU 4107 Gangster Segment Tree线段树

这道题也有点新意,就是需要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提高速度的目的. 本题过的人很少,因为大部分都超时了,我严格按照线段树的方法去写,一开始居然也超时. 然后修补了两个地方就过了,具体修改的地方请参看程序. 知道最大值段和最小值段,然后修补一下就能过了.不是特别难的题目. #include <stdio.h> #include <string> #include <algorithm> using namespace std; c

Geeks Splay Tree Insert 树的插入操作

Splay树的插入操作,只需要处理好插入节点的孩子节点就可以了,最重要的是不要破坏了BST的基本规则. 因为高度并不是Splay树的首要因素,所以插入的时候也是使用splay操作,然后在根节点插入. 参考:http://www.geeksforgeeks.org/splay-tree-set-2-insert-delete/ 对比一下使用插入创建的树和手工创建数的区别,先序遍历的结果: #pragma once #include<stdio.h> #include <stdlib.h&g

【HDOJ 5834】Magic boy Bi Luo with his excited tree(树型DP)

[HDOJ 5834]Magic boy Bi Luo with his excited tree(树型DP) Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Bi Luo is a magic boy, he also has a migic tree,

poj 3321:Apple Tree(树状数组,提高题)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18623   Accepted: 5629 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

【POJ 2486】 Apple Tree(树型dp)

[POJ 2486] Apple Tree(树型dp) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8981   Accepted: 2990 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each

[转] Splay Tree(伸展树)

好久没写过了,比赛的时候就调了一个小时,差点悲剧,重新复习一下,觉得这个写的很不错.转自:here Splay Tree(伸展树) 二叉查找树(Binary Search Tree)能够支持多种动态集合操作.因此,在信息学竞赛中,二叉排序树起着非常重要的作用,它可以被用来表示有序集合.建立索引或优先队列等. 作用于二叉查找树上的基本操作的时间是与树的高度成正比的.对一个含n各节点的完全二叉树,这些操作的最坏情况运行时间为O(log n).但如果树是含n个节点的线性链,则这些操作的最坏情况运行时间

hdu 1754 splay tree伸展树 初战(单点更新,区间属性查询)

题意:与区间查询点更新,点有20W个,询问区间的最大值.曾经用线段树,1000+ms,今天的伸展树,890没ms,差不多. 第一次学习伸展树,一共花了2个单位时间,感觉伸展树真很有用,也很好玩.现在只学了一点点.切个点更新试试. 大致思路:用编号(数组)作为树的键值建树,每插一个数,沿路节点更新最大值(每个结点有一个附加信息标记以之为子树的树所有点的最大值).所以,查询时[i,j],只要把i-1伸展到树根,把j+1伸展到I-1下面,那么j+1的左子树就是要的区间了!查该子树根值信息即可(特判端点

页面设计--Tree目录树

Tree目录树控件属性: 根据数据集合来配置相应的信息 加载模式有自动加载.自定加载 web中显示效果图: