常常在项目中,经常会遇到树形结构的使用:大致有以下的需求:
点击一个节点,查出该节点下的所有子孙节点所对应的数据。删除一个节点,需要把所有的该节点的子孙节点找出来后,再根据节点删除。
在做项目的时候,使用到easyui的树形结构,或者使用ztree。
在使用easyui的时候:我常常会封装好一个类:
public class TreeUtil {
public final static String getRoot(List<JsonTreeData> ls)
{
String rootid=null;
int sum=0;
for(int i=0;i<ls.size();i++)
{
for(int j=0;j<ls.size();j++)
{
if(ls.get(i).getPid().equals(ls.get(j).getId()))
{
sum=0;
break;
}
else
{
sum++;
}
}
if(sum==ls.size())
{
rootid=ls.get(i).getPid();
break;
}
}
return rootid;
}
public final static List<JsonTreeData> getfatherNode(List<JsonTreeData> treeDataList) {
List<JsonTreeData> newTreeDataList = new ArrayList<JsonTreeData>();
for (JsonTreeData jsonTreeData : treeDataList) {
if(jsonTreeData.getPid()==null) {
//获取父节点下的子节点
jsonTreeData.setChildren(getChildrenNode(jsonTreeData.getId(),treeDataList));
jsonTreeData.setState("open");
newTreeDataList.add(jsonTreeData);
}
}
return newTreeDataList;
}
/**
* @Title: getChildrenNode
* @Description 方法描述: 子节点
* @param 设定文件: @param pid
* @param 设定文件: @param treeDataList
* @param 设定文件: @return
* @return 返回类型:List<JsonTreeData>
* @throws
* @date 最后修改时间:2015年6月9日 下午6:39:50
*/
private final static List<JsonTreeData> getChildrenNode(String pid , List<JsonTreeData> treeDataList) {
List<JsonTreeData> newTreeDataList = new ArrayList<JsonTreeData>();
for (JsonTreeData jsonTreeData : treeDataList) {
if(jsonTreeData.getPid() == null) continue;
//这是一个子节点
if(jsonTreeData.getPid().equals(pid)){
//递归获取子节点下的子节点
jsonTreeData.setChildren(getChildrenNode(jsonTreeData.getId() , treeDataList));
newTreeDataList.add(jsonTreeData);
}
}
return newTreeDataList;
}
private static List<JsonTreeData> newTreeDataLists = new ArrayList<JsonTreeData>();
public final static List<JsonTreeData> getAllChild(String pid , List<JsonTreeData> treeDataList) {
for (JsonTreeData jsonTreeData : treeDataList) {
if(jsonTreeData.getPid() == null) continue;
//这是一个子节点
if(jsonTreeData.getPid().equals(pid)){
newTreeDataLists.add(jsonTreeData);
getAllChild(jsonTreeData.getId(),treeDataList);
//递归获取子节点下的子节点
// jsonTreeData.setChildren(getChildrenNode(jsonTreeData.getId() , treeDataList));
}
}
return newTreeDataLists;
}
}
实体类:
public class JsonTreeData {
private String id;
private String text;
private String state;
private String pid;
private List <JsonTreeData>children;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public List<JsonTreeData> getChildren() {
return children;
}
public void setChildren(List<JsonTreeData> children) {
this.children = children;
}
}
思路:从数据库拿到所有的数据后,构建树形结构:形成一棵树。
如果想通过一个节点获取他的子孙节点,可以调用getAllChild() 获得所有其子孙节点的id。
使用ztree的时候,更方便,只需将数据从数据库拿出来,转成ztree所需的数据结构,然后转为json,传到前台,ztree自动解析,形成树。如果想做节点删除,或节点查询的功能:一般会用到in。ztree提供api获取节点的所有子孙节点的id,将这些id传递到后台后,使用In语句来做节点删除和节点查询:
具体代码如下:
使用到的api有:
function OnRightClick(event,treeId,treeNode)
{
$("#categoryid").val(treeNode.id);
$("#categoryvalue").val(treeNode.name);
var a=new Array();
a=getChildren(a,treeNode); //获取节点的所有子孙节点
var category= a.join(","); //将数组的数据弄成以逗号隔开的方式,传递至后台,后台拿到数据后,解析,使用in来查询。
$("#categoryids").val(category);
$('#sonmenu').menu('show', {
left: event.pageX,
top: event.pageY
});
}
function getChildren(ids,treeNode){
ids.push(treeNode.id);
if (treeNode.isParent){ //如果是父节点,即还有子节点,那么使用递归的方式将它的所有子孙节点找出来,然后放到数组里
for(var obj in treeNode.children){
getChildren(ids,treeNode.children[obj]);
}
}
return ids;
}
总结:其实对于树形结构,最核心的是递归算法的实现。使用ztree,也是需要在前台做递归实现找到一个节点的所有子孙节点。
两种方式:
1.从前台找子孙节点,直接将所有的子孙节点传递到后台。这样就不需要后台获得一个节点后,去搜索所有的数据(从数据库中拿数据)。
2.传递一个节点的id到后台,后台根据此id获取该节点下的所有子孙节点(又再次从数据库中取数据),这样就很浪费服务器端的资源。所以此种方法不适合采取。