菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树
状菜单数据接⼝)
初学Web端开发,今天是第⼀次将所学做随笔记录,肯定存在多处⽋妥,望⼤家海涵;若有不⾜,望⼤家批评指正。
进实验室后分配到的第⼀个项⽬,需要制作⼀个不确定层级树形菜单的数据接⼝,对于从来没实战编过程的我,存在太多需要学习的地⽅。开发环境:Atom;
语⾔:javascript;
其他:nodejs;mysql;express;
输⼊:通过sql语句转换出的⼀个个JSON对象,如:其中id为唯⼀编号,parent为其⽗级的id号。
1 [
2 {
3 "id": 1,
4 "name": "111",
5 "parent": null,
6 "icon": "555,,"
7 },
8 {
9 "id": 2,
10 "name": "极地测试菜单2",
11 "parent": 1,
12 "icon": "/img/002.png"
13 },
14 {
15 "id": 4,
16 "name": "555",
17 "parent": 2,
18 "icon": "88"
19 },
20 {
21 "id": 5,
22 "name": "ddd",
23 "parent": 2,
24 "icon": "555.png"
25 },
26 {
27 "id": 6,
28 "name": "666",
29 "parent": 4,
30 "icon": null
31 },
32 {
33 "id": 7,
34 "name": "777",
35 "parent": 5,
36 "icon": null
37 },
38 {
39 "id": 9,
40 "name": "8888",
41 "parent": 1,
42 "icon": nullmysql安装教程菜鸟课程
43 },
44 {
45 "id": 10,
46 "name": "9999",
47 "parent": 9,
48 "icon": null
49 },
50 {
51 "id": 11,
52 "name": "10000",
53 "parent": 1,
54 "icon": null
55 }
56 ]
输出:树状JSON结构
1 {
2 "id": 1,
3 "name": "111",
4 "parent": null,
5 "icon": "555,,",
6 "sub": [
7 {
8 "id": 2,
9 "name": "极地测试菜单2",
10 "parent": 1,
11 "icon": "/img/002.png",
12 "sub": [
13 {
14 "id": 4,
15 "name": "555",
16 "parent": 2,
17 "icon": "88",
18 "sub": [
19 {
20 "id": 6,
21 "name": "666",
22 "parent": 4,
23 "icon": null,
24 "sub": []
25 }
26 ]
27 },
28 {
29 "id": 5,
30 "name": "ddd",
31 "parent": 2,
32 "icon": "555.png",
33 "sub": [
34 {
35 "id": 7,
36 "name": "777",
37 "parent": 5,
38 "icon": null,
39 "sub": []
40 }
41 ]
42 }
43 ]
44 },
45 {
46 "id": 9,
47 "name": "8888",
48 "parent": 1,
49 "icon": null,
50 "sub": [
51 {
52 "id": 10,
53 "name": "9999",
54 "parent": 9,
55 "icon": null,
56 "sub": []
57 }
58 ]
59 },
60 {
61 "id": 11,
62 "name": "10000",
63 "parent": 1,
64 "icon": null,
65 "sub": []
66 }
67 ]
68 }
即将从mysql中取出的⼀条⼀条JSON数据,按照parent所指向的id号,转变为树桩JSON结构,供AngularJS框架⾃动⽣成树桩菜单。⽰例图:
变量声明:allMenu为初始输⼊的JSON数据格式,即包含⼀条⼀条JSON对象的数组。
对象的sub属性放置当前对象的所有⼦节点数组。
思想:利⽤递归/循环进⾏树的层级遍历。
⽐如输⼊⼀个根节点对象,⾸先应对allMenu遍历寻parent为根节点id的所有对象(⽅法命名为findItemChild),并将其置⼊⼀个临时数组childlist中。然后对该childlist进⾏遍历,对其中每⼀个对象利⽤递归⽅法,返回该对象的childList并添加进当前对象的sub中,往复递归。举个例⼦:即当⽅法输⼊id=1的对象后,findItemChild⽅法通过遍历会返回⼀个数组[{id:2,parent:1,...},{id:9,parent:1,...},
{id:11,parent:1,...}],之后对该数组进⾏遍历,即将id=2的对象递归输⼊⽅法,并将获取的childlist遍历继续递归。。。。即树的层级遍历。算法:
输⼊:JSON对象item
function getAllChild(res){
①获取所有⽗级为根节点id的⼦对象数组childlist
②若childlist为空,则返回[]
③若childlist不为空,遍历childlist,并对每⼀个childlist[k]递归调⽤getAllChild(childlist[k])赋予childlist[k].sub
④将childlist输⼊res.sub
⑤返回childlist
}
输出:以对象item为根节点的树状JSON对象
代码:
('/:id', function(req, res, next) {
2
3
4 Connection(function(err, connection) {
5if (err) return next(err);
6
7 connection.query('SELECT * from menuitems ', function(err, rows, fields) {
8if (err) throw err;
9//get all data
10var result = [];//存放起始对象
11var allMenu = rows;//获取sql出的全部json对象
12for(i=0;i<allMenu.length;i++){
13if(allMenu[i].id == req.params.id){
14 result.push(allMenu[i]) ;//根据id号获取根对象
15break;
16 }
17 }
18//judege result exist or not
19if(result.length==0){
20
21return res.json('Failed! id is not exist!');
22
23 }else{
24
25 result.sub=[];
26 result.sub=getAllChild(result);//调⽤
27 res.json(result[0]);
28
29 }
30//find some item all child
31function findItemChild(item){
32var arrayList=[];
33for(var i in allMenu){
34if(allMenu[i].parent == item.id){
35 arrayList.push(allMenu[i]);
36 }
37 }
38return arrayList;
39 }
40//get all child
41function getAllChild(array){
42var childList=findItemChild(array[0]);
43if(childList == null){
44return [];
45 }
46else{
47for(var j in childList){
48 childList[j].sub=[];
49 childList[j].sub=getAllChild([childList[j]]);
50 }
51 array[0].sub=childList;
52 }
53return childList;
54
55 }
56 });
57 });
58 });
代码执⾏过程:
getAllChild([id=1])
childlist=[{id:2,parent:1,...},{id:9,parent:1,...},{id:11,parent:1,...}];
for(id=2 id=9 id=11)
↓
childlist[id=2].sub=?
↓
getAllChild([id=2]);
childlist=[{id:4,parent:2,...},{id:5,parent:2,...}];
for(id=4 id=5)
↓
childlist[id=4].sub=?
↓
getAllChild([id=4]);
childlist=[{id:6,parent:4,...}];
for(id=6)
↓
childlist[id=6].sub=?
↓
getAllChild([id=6]),return [];//到底,依次往上返回,将childlist逐步扩充,直到最终返回allchild;
扩充:返回所有树状菜单,即寻所有JSON数据构成的森林。思想是通过给森林构造⼀个根节点转换为树,再利⽤上述⽅法实现。
('/', function(req, res, next) {
2
3 Connection(function(err, connection) {
4if (err) return next(err);
5 connection.query('SELECT * from menuitems ', function(err, rows, fields) {
6if (err) throw err;
7//get all data
8//create a id= null root for forest
9var temp_parent={"id":null,"sub":[]};//新建id为null的对象做为森林的根
10var result=[];
11var allMenu = rows;
12
13 result.push(temp_parent) ;
14
15var output = getAllChild(result);
16if(output.length==0){
17//if our database do note have any data
18return res.json('Failed! do not have any data!');
19 }else {
20 res.json(output);
21 }
22
23//find some item all child //⽅便阅读依然放上此⽅法
24function findItemChild(item){
25var arrayList=[];
26for(var i in allMenu){
27if(allMenu[i].parent == item.id){
28 arrayList.push(allMenu[i]);
29 }
30 }
31return arrayList;
32 }
33//get all child //⽅便阅读依然放上此⽅法
34function getAllChild(array){
35var childList=findItemChild(array[0]);
36if(childList == null){
cssci集刊202137return [];
38 }
continue跳出for循环39else{
40for(var j in childList){
41 childList[j].sub=[];
42 childList[j].sub=getAllChild([childList[j]]);
43 }
44 array[0].sub=childList;
45 }
46return childList;
47
mysql打不开
48 }
49
50 });
51
52 });
53 });
总结:通过javascript语⾔利⽤NodeJS结合mysql可以实现从后台拿到JSON数据后,将数据构造成树状结构的形式供前端使⽤。这种Javascript全栈开发⽅式还有很多需要学习。未来的路还很长,加油!
递归的写法需要时常琢磨寻好的返回⽅式,在本⽂的思想下,递归⽅法的输⼊与返回的形式应统⼀,防⽌程序陷⼊死循环或不可执⾏,实在⽆法下⼿时应该通过画流程图的形式判断递归的有效性。递归在树层级⽐较深时肯定会耗费⼤量计算时间,因此之后通过学习寻更好的解决⽅法。
linux常用编辑命令kotlin教程培训tips:由于本⼈菜鸟⼀枚,所述拙见仅供⾃⼰学习总结,第⼀次写博客~若对您造成错误影响请批评指正。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论