古语有云: 万恶淫为首,百善孝为先。 我们后辈当自勉。

上一章简单介绍了JS数组的交并差补运算(二十三),如果没有看过,​​请观看上一章​​。

一. 对象数组的递归排序

在项目开发中,老蝴蝶常常遇到这样的问题, 后端返回一个对象集合,如权限的表, 有 id,parentId,name 这样的自身关联的表, 在后端查询时,查询出来了一些数据,但是这些数据通常是错综复杂的,排序并不明显。 在Oracle 数据库中,可以通过 start with … connect by …语句来进行查询,但是在MySQL数据库中没有这样的用法。 所以,有时候,前端排序也是非常重要的。 这个方法,就是通过 子与父之间的联系,进行相应的排序, 需要id,parentId 这样的字段来进行指定,不需要级别来指定。 如果没有父的话,那么parentId=0,或者是空。

如一个权限表:

JS对象数组的递归排序(二十四)_数组

后端返回给前端的数据格式是,

JS对象数组的递归排序(二十四)_JS对象数组以Tree排序_02

太多,老蝴蝶这儿就简单截个屏两个了。

在表格中,用的是bootstrap-table 表格,响应的结果是:

function handleClientData(res){
var privilegeList=res.privilegeList?res.privilegeList:[];
return privilegeList;
}

JS对象数组的递归排序(二十四)_数组_03

发现,这种展示方式很明显是不可以的。

可以通过一个方法,将响应的对象数组进行改变一下。

二. 通过递归,排序出新的集体。

方法中所用的 Map, 即new Map(), 并不是 JS的Map,而是老蝴蝶找的Map. 关于Map的内容,可以看老蝴蝶以前写的文章: ​​JS的Map详细形式(十八)

深复制 DeepCopy() ,也可以参考老蝴蝶以前写的文章: ​​JS的数组和对象深层拷贝(二十一)​​

/**
*
* @param data 要排序的对象数组
* @param idName id的编号名称
* @param pIdName 父级的编号名称
*/
function listToTree(data,idName,pIdName){
//最后结果的集合
var resultData=[];
//存储 父下面的所有的子的集合。 key为父,value为子的集合。
var parentMap=new Map();

//存储第一级别,即刚开始的那个集合。
var firstLevelData=[];

//2。 为了避免造成对原来数据的干扰,进行一个深度的Copy.
var resultDeepList=deepCopy(data);

$.each(resultDeepList,function(idx,item){
var oldItem=item;
if(!item[pIdName]){ //为空,或者值是0时,设置成-1.
item[pIdName]=-1;
}
//放置父级
if(parentMap.containsKey(item[pIdName])){
parentMap.get(item[pIdName]).push(oldItem);
}else{
var arr=new Array();
arr.push(oldItem);
parentMap.put(item[pIdName],arr);
}
//取出第一级别的那些集合。

if(item[pIdName]==-1){
firstLevelData.push(oldItem);
}
})
diGuiTree(resultData,firstLevelData,parentMap,idName);

return resultData;
}

function diGuiTree(resultData,data,parentMap,idName){ //放置过来的,是每一个的树。
if(data!=null&&data.length>0){
for(var i=0,length=data.length;i<length;i++){
var single=data[i];
resultData.push(single);
//看是否有子级。
if(parentMap.get(single[idName])){ //有子级
var sonList=parentMap.get(single[idName]);
if(sonList&&sonList.length>0){
diGuiTree(resultData,sonList,parentMap,idName);
}
}
}

}
}

三. 响应时,调用新方法

写好了这个方法,在响应时进行调用。

function handleClientData(res){
var privilegeList=res.privilegeList?res.privilegeList:[];
//return privilegeList; //以前的调用形式
var resultData=listToTree(privilegeList,"id","parentid");
return resultData;
}

刷新表格,展示:

JS对象数组的递归排序(二十四)_JS对象数组以Tree排序_04

四. 补充

展示有层次,是因为对 name那一列进行了设置样式。

<th data-field="name" data-align="center" data-cell-style="nameCellStyle">名称</th>
function nameCellStyle(value,row,index,field){
var level=row.level;
return {
css:{
"text-align":'left !important',
"padding-left":(level*40)+"px"
}
}
}

谢谢!!!