您的位置:首页 > Web前端 > JavaScript

Tree资源树的实战研究

2016-04-07 14:13 483 查看

背景简介:

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

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



一、自己动手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~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  XML javascript Ajax