- js递归遍历树
- 2010-05-27 07:26:11
树的结构可以很简单的看着是N个父子关系,这和许多Object就很像,在JAVA中往map中放map这可以很好的表现出这种关系。基于这种关系,从某个节点出发,把他们遍历出来也是很简单的事情。
所以首先我们把一组有父子关系的数据放在一个OBJECT里面,并封装一个treeList类。往往这一步是在最初始的时候做,所以可以写这样的一个方法:
initData:function(arr){//arr是一组有父子关系的数据,这里的关系表现在parentId和id两个字段上。当然可以是其他字段。
for(var i=0; i if(!treeList.treeData[arr[i].parentId]){
treeList.treeData[arr[i].parentId] = {};//用parentId作为所有父节点的KEY
treeList.treeData[arr[i].parentId][arr[i].id] = arr[i];//arr[i].id作为某个具体孩子节点对象的KEY
}
},一组数据都有一个值不可重复的主键,比如这里的ID。praentId其实指向的是也是某个ID,拿这个ID作为KEY,是比较靠谱的一种做法。
下面就可以遍历整个树了。可以从一节点pid开始遍历。
getTree:function(pid){
for(var k in treeList.treeData[pid]){
if(treeList.treeData[k]&&k!=0){
treeList.getTree(k);//如果有值为K的父节点,递归查找他的孩子节点
}
treeList.treeData[pid][k];//这里的treeList.treeData[pid][k]就是key值为pid下面的孩子节点对象
}
}
一切就就是这样简单!
按照这个方法,在一个项目中我写了下面的一个类,主要是在DOM里插入和操作这棵树。/*
* treeList : tree control class of operation menu
* 操作菜单树结构控制类
* by : tangq
* version : 1.0
* date: 2010-4-14
* updateTime: 2010-4-15*/
var treeList = {
/*
* [object treeList.treeData] : The format of data stored in the treeData
* 将格式后的数据存储在treeData
*/
treeData:{},
/*
* [String treeList.htmlDom] :
* 当前treelist生成的HTMLElement
*/
htmlDom:[],
/*
* [funtion treeList.init] : initialization treeList, and HTML text into the specified domElement inside.
* 在DOM中初始化treeList,并将HTML文本插入指定的domElement里面。
* @param id[String] : dom中节点的ID
*/
init:function(id,model){
if(model){
treeList.model = model;
}
/*
* 默认状态下从0级开始遍历树
*/
if(treeList.treeData[0]){
treeList.getTree(0);
}
/*
* 将一个DOMlist添加到当前document中
*/
var dom = document.createElement('ul');
dom.id = 'treelist-box';
dom.className = 'treelist';
for(var i=0; i dom.appendChild(treeList.htmlDom[i]);
}
document.getElementById(id).appendChild(dom);
},
/*
* [funtion treeList.get] : Get a property in treelist object
* 得到treelist对象里的某个属性值
* @param id[number] : 元数据的ID treeList.treeData的KEY值
* @param value[string] : 要属性的 若改属性不存在 返回null
*/
get:function(id,value){
for(var p in treeList.treeData){
for(var k in treeList.treeData[p]){
if(k==id){
if(treeList.treeData[k])return null;
return treeList.treeData[p][k][value];
}
}
}
return null;
},
/*
* [funtion treeList.initData] : External call interface of data initially treelist
* 外部调用接口 初始treelist的数据
* @param arr[Array] : 外部获取的一个treelist数组
*/
initData:function(arr){
treeList.htmlDom = [];
for(var i=0; i if(!treeList.treeData[arr[i].parentId]){
treeList.treeData[arr[i].parentId] = {};
}
treeList.treeData[arr[i].parentId][arr[i].id] = arr[i];
}
},
/*
* [String model]:设置节点模板类型
*/
model:'icon',
/*
* [funtion treeList.getTmpStr] : Generating node template
* 生成节点模版
*/
getTmpStr:function(){
if(treeList.model=='icon'){
return '#name#';
}
if(treeList.model=='checkbox'){
return '#name#';
}
if(treeList.model=='none'){
return '#name#';
}
return '';
},
/*
* [funtion treeList.getTree] : The depth of a parent node traversal
* 对一个父节点进行深度遍历
* @param pid[Number] : 节点ID
* EXP:getTree(0)-> 遍历父节点为0下的所有子节点
*/
getTree:function(pid){
var modelstr = treeList.getTmpStr();
for(var k in treeList.treeData[pid]){
var dom = document.createElement('li');
dom.id = 'treelist-'+k;
var s = modelstr.replace(/#id#/g,k).replace(/#name#/g,treeList.treeData[pid][k].name).replace(/#value#/g,treeList.treeData[pid][k].value);
if(treeList.treeData[k]&&k!=0){
dom.className = 'treelist-level-'+pid+' treelist-parentNode';
dom.innerHTML = ''+s;
treeList.htmlDom.push(dom);
treeList.getTree(k);
}else{
dom.className = 'treelist-level-'+pid;
dom.innerHTML = ''+s;
treeList.htmlDom.push(dom);
}
treeList.treeData[pid][k].dom = dom;
(function(dom,k){
dom.onclick = function(){
treeList.click(k);
};
})(dom,k);
}
},
/*
* [funtion treeList.click] : node's click Event
* 节点点击事件
* @param id[Number] : 节点索引值,0开始
* 如果是父节点 将调用父节点事件
*/
click:function(id){
for(var p in treeList.treeData){
for(var k in treeList.treeData[p]){
if(k==id){
if(treeList.treeData[k]){
treeList.parentClick(k);
}else{
treeList.select('treelist-'+k);
}
break;
}
}
}
},
/*
* [funtion treeList.parentClick] : node's click Event
* 父节点节点点击事件
* @param id[Number] : treeList.treeData的KEY值 即元数据某一对象的ID
* 收起或展开子节点
*/
parentClick:function(id,m){
var lispan = document.getElementById('treelist-'+id).getElementsByTagName('span').item(0);
var action;
if(!m){
if(lispan.className.indexOf('treeicon-open')!=-1){
action = 'close';
}else{
action = 'open';
}
}else{
action = m;
}
for(var k in treeList.treeData[id]){
if(treeList.treeData[k]){
treeList.parentClick(k,action);
}
}
var lis = document.getElementById('treelist-box').getElementsByTagName('li');
for(var i=0; i if(lis.item(i).className.indexOf('treelist-level-'+id)!=-1){
if(action=='open'){
lis.item(i).style.display = 'block';
}else{
lis.item(i).style.display = 'none';
}
}
}
if(action=='open'){
lispan.className = lispan.className.replace('treeicon-close','treeicon-open');
}else{
lispan.className = lispan.className.replace('treeicon-open','treeicon-close');
}
},
/*
* [funtion treeList.select] : A node is selected
* [String|Number treeList.selectedIndex] : tree selected Index or id
* 选中某个节点
* @param num[Number] : 节点索引值,0开始
*/
selectedIndex:null,
select:function(index){
selectedIndex = treeList.selectedIndex;
if(index==selectedIndex)return;
for(var i=0; i if(index.constructor == Number&&index==i){
treeList.htmlDom[index].className += ' selected';
}else if(treeList.htmlDom[i].id == index){
treeList.htmlDom[i].className += ' selected';
}
if(selectedIndex!=null&&selectedIndex.constructor == Number&&selectedIndex==i){
treeList.htmlDom[i].className = treeList.htmlDom[i].className.replace(' selected','');
}else if(selectedIndex!=null&&treeList.htmlDom[i].id == selectedIndex){
treeList.htmlDom[i].className = treeList.htmlDom[i].className.replace(' selected','');
}
}
treeList.selectedIndex = index;
},
/*
* [funtion treeList.addEvent] : Add a events to treelist nodes
* 给treelist节点添加监听事件
* @param type[String] : 事件类型
* @param fun[function] : 回调函数
*/
addEvent:function(type,fun){
for(var i=0; i (function(dom,type,fun){
xui.util.Event.on(dom,type,fun);
})(treeList.htmlDom[i],type,fun);
}
}
}/*
* examples
*//*
treeList.getTree(0);
alert(treeList.html);
*/
/*
* used it in html:code in head:
code in dom:
code when dom loaded:
*/
示例中common.css为树HTML结构的样式,treelist.js是数据源,可以是这样的:var arry = [{"parentId":"0","id":0,"name":"根","link":"www.g.cn"}......];
然后初始化它:treeList.initData(arry);
- js,javascript,java,web,wd,map
- web
- 116
- 0