您的位置:首页 > Web前端 > Node.js

zTree的联想[将数据表封装成自定义TreeNode,再将TreeNode生成json字串

2011-11-27 14:10 621 查看
由zTree的示范我们看到zTree支持多种数据类型,我认为json是最好的,项目中json肯定来自数据库,不可能就这样纯粹静态的,如何将数据库表中的属性信息生成json呢,这是关键问题,比如数据表读出的数据可能如下:

//用一个集合模拟数据表的内容,也就是一下集合的内容完全可以查询自数据库
List<SysFunction> treeList = new ArrayList<SysFunction>();
treeList.add(new SysFunction("L01", null, "营销管理"));
treeList.add(new SysFunction("L02",null,"客户管理"));
treeList.add(new SysFunction("L03",null,"服务管理"));
//营销管理的子功能
treeList.add(new SysFunction("L0101","L01","创建销售机会"));
treeList.add(new SysFunction("L0102","L01","指派销售机会"));
treeList.add(new SysFunction("L0103","L01","制定开发计划"));
treeList.add(new SysFunction("L0104","L01","执行开发计划"));
//指派销售机会的子功能
treeList.add(new SysFunction("L010201","L0102","经理指派"));
treeList.add(new SysFunction("L010202","L0102","主管指派"));
//客户管理的子功能
treeList.add(new SysFunction("L0201","L02","客户信息管理"));
treeList.add(new SysFunction("L0202","L02","客户流失管理"));
//服务管理子功能
treeList.add(new SysFunction("L0301","L03","咨询服务管理"));
treeList.add(new SysFunction("L0302","L03","投诉服务管理"));
treeList.add(new SysFunction("L0303","L03","查询服务管理"));





这里的SysFunction类封装的是系统功能表,这个类的定义如下:

/**
* 系统功能对象
* */
class SysFunction {

private String code;
private String parentCode;
private String title;

/**功能编号*/
public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}
/**父级功能编号*/
public String getParentCode() {
return parentCode;
}

public void setParentCode(String parentCode) {
this.parentCode = parentCode;
}
/**功能名称,现在树上的节点文本*/
public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public SysFunction(String code, String parentCode, String title) {
super();
this.code = code;
this.parentCode = parentCode;
this.title = title;
}

public SysFunction() {
super();
}
}


每个功能可能有一个父功能,也可能没有,如下将他们封装成Json字串呢?

定义TreeNode类代表树形节点,注意观察这个类,关键代码都在里面实现了,比如如何让节点携带信息、如何将节点解析成JSON字串、如何向一个节点及子孙节点添加属性信息:

/**自定义的树节点*/
class TreeNode {
// 节点携带的值
private Map<String, Object> tag;

// 儿子节点
private List<TreeNode> nodes;

/**节点信息键值对,该属性不会为空指针,但可能没有键值对存在[就是map.size()==0]*/
public Map<String, Object> getTag() {
if (tag == null)
tag = new HashMap<String, Object>();
return tag;
}

public void setTag(Map<String, Object> tag) {
this.tag = tag;
}

/**获得所有子节点,该属性不会为空指针,但可能没有集合元素存在*/
public List<TreeNode> getNodes() {
if (nodes == null)
nodes = new ArrayList<TreeNode>();
return nodes;
}

public void setNodes(List<TreeNode> nodes) {

this.nodes = nodes;
}

public TreeNode(Map<String, Object> tag, List<TreeNode> nodes) {
super();
this.tag = tag;
this.nodes = nodes;
}

public TreeNode() {
super();
}

public TreeNode(Map<String, Object> tag) {
super();
this.tag = tag;
}

/**
* <pre>
* 		将当前TreeNode解析为JSON字串 构造的目标格式示例:
* 		{
* 			id:1,
* 			name:'手机',
* 			nodes:[
* 				{id:11,name:'诺基亚'},
* 				{id:12,name:'三星',nodes:[
* 					{id:121,name:'I9000(联通版)'},
* 					{id:122,name:'I9000(移动版)'},
* 					{id:123,name:'Galaxy Naos'}
* 				]},
* 				{id:13,name:'索爱'}
* 			]
* 		}
* </pre>
* */
public String toJson(){
if (this.getNodes().size() == 0)
throw new RuntimeException("节点不能没有任何属性");
return parseTreeNode(this);
}

@Override
public String toString() {
// TODO Auto-generated method stub
return toJson();
}

/**
* <pre>
* 		将当前TreeNode解析为JSON字串 构造的目标格式示例:
* 		{
* 			id:1,
* 			name:'手机',
* 			nodes:[
* 				{id:11,name:'诺基亚'},
* 				{id:12,name:'三星',nodes:[
* 					{id:121,name:'I9000(联通版)'},
* 					{id:122,name:'I9000(移动版)'},
* 					{id:123,name:'Galaxy Naos'}
* 				]},
* 				{id:13,name:'索爱'}
* 			]
* 		}
* </pre>
* */
private String parseTreeNode(TreeNode node) {
if (node == null)
throw new RuntimeException("节点不能为空");
StringBuilder nodeBuilder = new StringBuilder("{");// JSON对象开始
// 把Map中的键值对构造成json对象属性
for (Map.Entry<String, Object> kvp : node.getTag().entrySet()) {
if (kvp.getValue().getClass() == String.class)
nodeBuilder.append(kvp.getKey() + ":'" + kvp.getValue() + "',");
else
nodeBuilder.append(kvp.getKey() + ":" + kvp.getValue() + ",");
}

// 构造子节点
nodeBuilder.append("nodes:["); // 子节点开始
for (TreeNode cnode : node.getNodes()) {
if (cnode == null)
continue;
nodeBuilder.append(parseTreeNode(cnode) + ",");// 递归调用ParseTreeNode返回一个完整的JSON字串:"{属性1:value,属性2:value}"
}
if (nodeBuilder.charAt(nodeBuilder.length() - 1) == ',')// 去掉末尾逗号
nodeBuilder.deleteCharAt(nodeBuilder.length() - 1);
nodeBuilder.append("]"); // 子节点结束

nodeBuilder.append("}"); // JSON对象结束

return nodeBuilder.toString();
}

/**
* 向指定节点及其子孙节点添加一个属性
* @author jiang
* @param node	被放置属性的节点
* @param isrecursive	是否递归[当前节点的子孙节点]放置属性
* @param entries	放置的属性键值对
*/
private void _putProperty(TreeNode node,Boolean isrecursive,Map.Entry<String,Object>...entries) {
if (entries!=null)
for (Map.Entry<String, Object> entry : entries) {
node.getTag().put(entry.getKey(),entry.getValue());
}
if (!isrecursive)
return;
for (TreeNode n : node.getNodes()) {
_putProperty(n,isrecursive,entries);
}
}

/**
* 向指定节点及其子孙节点添加一个属性
* @author jiang
* @param node	被放置属性的节点
* @param isrecursive	是否递归[当前节点的子孙节点]放置属性
* @param entries	放置的属性键值对
*/
public void putProperty(Boolean isrecursive,Map.Entry<String,Object>...entries) {
_putProperty(this,isrecursive,entries);
}
}


下面这个类是使用这个TreeNode生成需要的json字串,这个类解决了一个最关键的问题:就是将List集合封装成了一棵树TreeNode

public class TreeService {

public String getTree() {

//用一个集合模拟数据表的内容,也就是一下集合的内容完全可以查询自数据库 List<SysFunction> treeList = new ArrayList<SysFunction>(); treeList.add(new SysFunction("L01", null, "营销管理")); treeList.add(new SysFunction("L02",null,"客户管理")); treeList.add(new SysFunction("L03",null,"服务管理")); //营销管理的子功能 treeList.add(new SysFunction("L0101","L01","创建销售机会")); treeList.add(new SysFunction("L0102","L01","指派销售机会")); treeList.add(new SysFunction("L0103","L01","制定开发计划")); treeList.add(new SysFunction("L0104","L01","执行开发计划")); //指派销售机会的子功能 treeList.add(new SysFunction("L010201","L0102","经理指派")); treeList.add(new SysFunction("L010202","L0102","主管指派")); //客户管理的子功能 treeList.add(new SysFunction("L0201","L02","客户信息管理")); treeList.add(new SysFunction("L0202","L02","客户流失管理")); //服务管理子功能 treeList.add(new SysFunction("L0301","L03","咨询服务管理")); treeList.add(new SysFunction("L0302","L03","投诉服务管理")); treeList.add(new SysFunction("L0303","L03","查询服务管理"));

//将这个从集合封装成TreeNode
//构造一个根节点
TreeNode rootNode = new TreeNode();
rootNode.getTag().put("id", "L1");
rootNode.getTag().put("name", "CRM系统");

//将这个集合封装成Map
Map<String,TreeNode> treeNodeMap = new HashMap<String,TreeNode>();
//下面的循环完成两个功能:
// 1.将所有对象封装成Map里面的键值对,且值是TreeNode类型
// 2.将没有父节点的TreeNode添加到根节点rootNode
for(SysFunction sysFunction:treeList){
TreeNode node = new TreeNode();
node.getTag().put("id",sysFunction.getCode());
node.getTag().put("name", sysFunction.getTitle());
treeNodeMap.put(sysFunction.getCode(),node);
if (sysFunction.getParentCode()==null || "".equals(sysFunction.getParentCode())){//如果没有父节点则添加到根节点
rootNode.getNodes().add(node);
}
}

//下面的代码建立节点之间的从属关系
for(int i=0;i<treeList.size();i++){
SysFunction sysFunction = treeList.get(i);
if (treeNodeMap.containsKey(sysFunction.getParentCode())){//如果当前功能的父级功能编号在treeNodeMap中存在
treeNodeMap
.get(sysFunction.getParentCode())//找出父节点
.getNodes() //父节点的子节点集合
.add( //向子节点集合添加子节点
treeNodeMap.get(sysFunction.getCode())//找出子节点
);
}
}

//给根节点和它的子孙节点添加一个属性信息(open:true),展开节点
rootNode.putProperty(true, new SimpleEntry<String,Object>("open",true));

return rootNode.toJson();
}
}


下面是我的示范页面,如何使用这个类,注意观察id等于treeDemo3的代码:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="demoStyle/demo.css" type="text/css"></link>
<link rel="stylesheet" href="zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript" src="jquery.ztree-2.6.js"></script>
<script type="text/javascript" src="asyncData/demoData.js"></script>
<script type="text/javascript">
var setting1 = {showline:true,checkable:true};
//json
var zTreeNodes1 = [
{ "name":"google", "url":"http://g.cn", "target":"_blank"},
{ "name":"baidu", "url":"http://baidu.com", "target":"_blank"},
{ "name":"sina", "url":"http://www.sina.com.cn", "target":"_blank"}
];
var zTreeNodes2 = [
{id:1,name:'手机',nodes:[
{id:11,name:'诺基亚',nodes:[
{id:111,name:'C6(音乐版)'},
{id:112,name:'X6(导航版)'},
{id:113,name:'5230(世博版)'}
]},
{id:12,name:'三星'},
{id:13,name:'索爱'},
{id:14,name:'多普达'}
]},
{id:2,name:'电脑'},
{id:3,name:'家电'}
];
window.onload=function(){
$("#treeDemo1").zTree(setting1,zTreeNodes1);
$("#treeDemo2").zTree({showline:true,checkable:false},zTreeNodes2);
$("#treeDemo3").zTree({showline:true,checkable:true},[<%=new TreeService().getTree() %>]);
};
</script>
</head>
<body>
<div class="zTreeDemoBackground" style="float:left;">
<ul id="treeDemo1" class="tree" style="float:left;"></ul>
</div>
<div class="zTreeDemoBackground"  style="float:left;">
<ul id="treeDemo2" class="tree"></ul>
</div>
<div class="zTreeDemoBackground"  style="float:left;">
<ul id="treeDemo3" class="tree"></ul>
</div>

</body>
</html>


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐