最近遇到用递归算法展示树形结构的需求,前端要展示的效果如下图所示:
image.png我们的数据格式如下,,这是简化后的数据:
[
{
"id": 1,
"level": 1,
"name": "ResourceName:syR",
"parentId": null,
"child": [
{
"id": 2,
"level": 2,
"name": "ResourceName:RjG",
"parentId": 1,
"child": [
{
"id": 3,
"level": 3,
"name": "ResourceName:Gvz",
"parentId": 2,
"child": []
}
]
},
{
"id": 4,
"level": 2,
"name": "ResourceName:R52",
"parentId": 1,
"child": [
{
"id": 5,
"level": 3,
"name": "ResourceName:R36",
"parentId": 4,
"child": []
}
]
}
]
}
]
我们调取后端的接口返回的数据层级是不确定的,这种情况下用递归算法展示是最好的。
因为我们的数据格式是第一级目录永远只有一个,所以在实现的时候我是先将第一层数据单独取出来,当然这在实际应用中可以按照自己的需求去实现,render方法代码如下:
render(){
const {
resourceOfAppInfoList,
}=this.props;
return (
<div className="tab-content height-300 overflow-auto">
<div className="tab-pane fade active in" id="tab-1">
<div className="exampleList m-auto p-t-5 active">
<div className="exampleList m-auto p-t-5 active">
{
resourceOfAppInfoList.map((item)=>{
return(
<div className="row m-0" key={"resourceOfAppInfoList"+item.id}>
<a className="width_20 pull-left text_gray f-s-16 m-t-5 m-r-5" href="javascript:;">
<i className="fa fa-angle-up"></i>
</a>
<div className="pull-left m-r-10">
<div className="row m-0" onClick={()=>this.changeSwitchShow(item.id)} style={{width: '52px', height: '32px', backgroundColor: '#eee',border:'1px solid #eee', borderRadius: '20px',cursor:' pointer'}}>
<div className="pull-right" style={{width: '30px', height: '30px', borderRadius: '50%', background: '#fff'}}></div>
</div>
</div>
<p className="text_gray m-t-5 p-t-1 m-b-0 pull-left">{item.name}</p>
{this.generateMenu(item.child)}
</div>
)
})
}
</div>
</div>
</div>
</div>
);
}
}
其中resourceOfAppInfoList就是我们从后端获取到的数据,数据格式就如上所示;
generateMenu就是我们的递归算法,代码如下:
/**
* 数结构展示
* @param menuObj
* @returns {Array}
*/
generateMenu(menuObj) {
let vdom = [];
if (menuObj instanceof Array) {
let list = [];
for (var item of menuObj) {
list.push(this.generateMenu(item));
}
vdom.push(
<div className="exampleBox">
<div className="vertical-box table-valign-middle">
<div className="exampleLine2 vertical-box-column" >
</div>
<div className="exampleLine vertical-box-column">
</div>
<div className="exampleCon vertical-box-column child">
{list}
</div>
</div>
</div>
);
} else {
vdom.push(
<div className="row m-0">
<div className="switcherBox pull-left m-r-10 m-t-15">
<div className="row m-0">
<div className="pull-left m-r-10">
<div className="row m-0" onClick={()=>this.changeSwitchShow(ary.id)} style={{width: '52px', height: '32px', backgroundColor: '#eee',border:'1px solid #eee', borderRadius: '20px',cursor:' pointer'}}>
<div className="pull-right" style={{width: '30px', height: '30px', borderRadius: '50%', background: '#fff'}}></div>
</div>
</div>
<p className="text_gray m-t-5 p-t-1 m-b-0 pull-left">{ary.name}</p>
</div>
</div>
{
menuObj.child.length!==0?
this.generateMenu(menuObj.child)
:null
}
</div>
);
}
return vdom;
}
最原始的一个树形结构就展示出来,实现的过程大概如下:
1.首先将第一级目录的child传到递归算法中,此时child是一个array,generateMenu方法中会先进入到if判断,展示子目录与父级目录的层级结构
2.在if方法中将child的第一条数据作为menuObj参数,调用自己的方法,此时menuObj是一个object对象,此时会进入到else判断,进行开关按钮和目录展示,在方法中继续把这个object对象的child作为menuObj参数调用自己的方法,此时又会先进入到if方法,重复如此
总的来说就是if方法中负责展示层级结构,else方法负责展示开关按钮和目录名称,我们就需要把数据传过去就可以了,debug调试的时候可以很清晰的看出数据的展示。
实现来说相对简单,但是网上的方法并不多,当然这种递归算法也可以进行一些数据的初始化,比如将数据展平,添加一些字段属性,可以灵活应用。
如有问题,欢迎指正!!!
网友评论