状菜单数据接⼝)
初学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\": null31 },32 {
33 \"id\": 7,
34 \"name\": \"777\35 \"parent\": 5,36 \"icon\": null37 },38 {
39 \"id\": 9,
40 \"name\": \"8888\41 \"parent\": 1,42 \"icon\": null43 },44 {
45 \"id\": 10,
46 \"name\": \"9999\47 \"parent\": 9,48 \"icon\": null49 },50 {
51 \"id\": 11,
52 \"name\": \"10000\53 \"parent\": 1,54 \"icon\": null55 }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对象代码:
1 router.get('/:id', function(req, res, next) { 2 3
4 pool.getConnection(function(err, connection) { 5 if (err) return next(err); 6
7 connection.query('SELECT * from menuitems ', function(err, rows, fields) { 8 if (err) throw err; 9 //get all data
10 var result = [];//存放起始对象
11 var allMenu = rows;//获取sql出的全部json对象12 for(i=0;i 14 result.push(allMenu[i]) ;//根据id号获取根对象15 break;16 }17 } 18 //judege result exist or not19 if(result.length==0){20 21 return 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 child31 function findItemChild(item){32 var arrayList=[];33 for(var i in allMenu){ 34 if(allMenu[i].parent == item.id){35 arrayList.push(allMenu[i]);36 }37 } 38 return arrayList;39 } 40 //get all child 41 function getAllChild(array){ 42 var childList=findItemChild(array[0]);43 if(childList == null){44 return [];45 }46 else{ 47 for(var j in childList){ 48 childList[j].sub=[]; 49 childList[j].sub=getAllChild([childList[j]]);50 } 51 array[0].sub=childList;52 } 53 return 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数据构成的森林。思想是通过给森林构造⼀个根节点转换为树,再利⽤上述⽅法实现。 1 router.get('/', function(req, res, next) { 2 3 pool.getConnection(function(err, connection) { 4 if (err) return next(err); 5 connection.query('SELECT * from menuitems ', function(err, rows, fields) { 6 if (err) throw err; 7 //get all data 8 //create a id= null root for forest 9 var temp_parent={\"id\":null,\"sub\":[]};//新建id为null的对象做为森林的根10 var result=[]; 11 var allMenu = rows;12 13 result.push(temp_parent) ;14 15 var output = getAllChild(result);16 if(output.length==0){ 17 //if our database do note have any data 18 return res.json('Failed! do not have any data!'); 19 }else { 20 res.json(output);21 }22 23 //find some item all child //⽅便阅读依然放上此⽅法24 function findItemChild(item){25 var arrayList=[];26 for(var i in allMenu){ 27 if(allMenu[i].parent == item.id){28 arrayList.push(allMenu[i]);29 }30 } 31 return arrayList;32 } 33 //get all child //⽅便阅读依然放上此⽅法34 function getAllChild(array){ 35 var childList=findItemChild(array[0]);36 if(childList == null){37 return [];38 }39 else{ 40 for(var j in childList){41 childList[j].sub=[]; 42 childList[j].sub=getAllChild([childList[j]]);43 } 44 array[0].sub=childList;45 } 46 return childList;47 48 }49 50 });51 52 });53 }); 总结:通过javascript语⾔利⽤NodeJS结合mysql可以实现从后台拿到JSON数据后,将数据构造成树状结构的形式供前端使⽤。这种Javascript全栈开发⽅式还有很多需要学习。未来的路还很长,加油! 递归的写法需要时常琢磨寻找好的返回⽅式,在本⽂的思想下,递归⽅法的输⼊与返回的形式应统⼀,防⽌程序陷⼊死循环或不可执⾏,实在⽆法下⼿时应该通过画流程图的形式判断递归的有效性。递归在树层级⽐较深时肯定会耗费⼤量计算时间,因此之后通过学习寻找更好的解决⽅法。 tips:由于本⼈菜鸟⼀枚,所述拙见仅供⾃⼰学习总结,第⼀次写博客~若对您造成错误影响请批评指正。 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- jqkq.cn 版权所有 赣ICP备2024042794号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务