初学Web端开发,今天是第一次将所学做随笔记录,肯定存在多处欠妥,望大家海涵;若有不足,望大家批评指正。

进实验室后分配到的第一个项目,需要制作一个不确定层级树形菜单的数据接口,对于从来没实战编过程的我,存在太多需要学习的地方。

开发环境:Atom;

语言:javascript;

其他:nodejs;mysql;express;

输入:通过sql语句转换出的一个个JSON对象,如:其中id为唯一编号,parent为其父级的id号。

 [
{
"id": 1,
"name": "111",
"parent": null,
"icon": "555,,"
},
{
"id": 2,
"name": "极地测试菜单2",
"parent": 1,
"icon": "/img/002.png"
},
{
"id": 4,
"name": "555",
"parent": 2,
"icon": "88"
},
{
"id": 5,
"name": "ddd",
"parent": 2,
"icon": "555.png"
},
{
"id": 6,
"name": "666",
"parent": 4,
"icon": null
},
{
"id": 7,
"name": "777",
"parent": 5,
"icon": null
},
{
"id": 9,
"name": "8888",
"parent": 1,
"icon": null
},
{
"id": 10,
"name": "9999",
"parent": 9,
"icon": null
},
{
"id": 11,
"name": "10000",
"parent": 1,
"icon": null
}
]

输出:树状JSON结构

 {
"id": 1,
"name": "111",
"parent": null,
"icon": "555,,",
"sub": [
{
"id": 2,
"name": "极地测试菜单2",
"parent": 1,
"icon": "/img/002.png",
"sub": [
{
"id": 4,
"name": "555",
"parent": 2,
"icon": "88",
"sub": [
{
"id": 6,
"name": "666",
"parent": 4,
"icon": null,
"sub": []
}
]
},
{
"id": 5,
"name": "ddd",
"parent": 2,
"icon": "555.png",
"sub": [
{
"id": 7,
"name": "777",
"parent": 5,
"icon": null,
"sub": []
}
]
}
]
},
{
"id": 9,
"name": "8888",
"parent": 1,
"icon": null,
"sub": [
{
"id": 10,
"name": "9999",
"parent": 9,
"icon": null,
"sub": []
}
]
},
{
"id": 11,
"name": "10000",
"parent": 1,
"icon": null,
"sub": []
}
]
}

即将从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对象

代码:

 router.get('/:id', function(req, res, next) {

   pool.getConnection(function(err, connection) {
if (err) return next(err); connection.query('SELECT * from menuitems ', function(err, rows, fields) {
if (err) throw err;
//get all data
var result = [];//存放起始对象
var allMenu = rows;//获取sql出的全部json对象
for(i=0;i<allMenu.length;i++){
if(allMenu[i].id == req.params.id){
result.push(allMenu[i]) ;//根据id号获取根对象
break;
}
}
//judege result exist or not
if(result.length==0){ return res.json('Failed! id is not exist!'); }else{ result.sub=[];
result.sub=getAllChild(result);//调用
res.json(result[0]); }
//find some item all child
function findItemChild(item){
var arrayList=[];
for(var i in allMenu){
if(allMenu[i].parent == item.id){
arrayList.push(allMenu[i]);
}
}
return arrayList;
}
//get all child
function getAllChild(array){
var childList=findItemChild(array[0]);
if(childList == null){
return [];
}
else{
for(var j in childList){
childList[j].sub=[];
childList[j].sub=getAllChild([childList[j]]);
}
array[0].sub=childList;
}
return childList; }
});
});
});

代码执行过程:

  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数据构成的森林。思想是通过给森林构造一个根节点转换为树,再利用上述方法实现。

  

 router.get('/', function(req, res, next) {

   pool.getConnection(function(err, connection) {
if (err) return next(err);
connection.query('SELECT * from menuitems ', function(err, rows, fields) {
if (err) throw err;
//get all data
//create a id= null root for forest
var temp_parent={"id":null,"sub":[]};//新建id为null的对象做为森林的根
var result=[];
var allMenu = rows; result.push(temp_parent) ; var output = getAllChild(result);
if(output.length==0){
//if our database do note have any data
return res.json('Failed! do not have any data!');
}else {
res.json(output);
} //find some item all child //方便阅读依然放上此方法
function findItemChild(item){
var arrayList=[];
for(var i in allMenu){
if(allMenu[i].parent == item.id){
arrayList.push(allMenu[i]);
}
}
return arrayList;
}
//get all child //方便阅读依然放上此方法
function getAllChild(array){
var childList=findItemChild(array[0]);
if(childList == null){
return [];
}
else{
for(var j in childList){
childList[j].sub=[];
childList[j].sub=getAllChild([childList[j]]);
}
array[0].sub=childList;
}
return childList; } }); });
});

总结:通过javascript语言利用NodeJS结合mysql可以实现从后台拿到JSON数据后,将数据构造成树状结构的形式供前端使用。这种Javascript全栈开发方式还有很多需要学习。未来的路还很长,加油!

递归的写法需要时常琢磨寻找好的返回方式,在本文的思想下,递归方法的输入与返回的形式应统一,防止程序陷入死循环或不可执行,实在无法下手时应该通过画流程图的形式判断递归的有效性。递归在树层级比较深时肯定会耗费大量计算时间,因此之后通过学习寻找更好的解决方法。

tips:由于本人菜鸟一枚,所述拙见仅供自己学习总结,第一次写博客~若对您造成错误影响请批评指正。

  

菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)的更多相关文章

  1. Node.js + MySQL 实现数据的增删改查

    通过完成一个 todo 应用展示 Node.js + MySQL 增删改查的功能.这里后台使用 Koa 及其相应的一些中间件作为 server 提供服务. 初始化项目 $ mkdir node-cru ...

  2. 零代码第一步,做个添加数据的服务先。node.js + mysql

    node.js + mysql 实现数据添加的功能.万事基于服务! 增删改查之添加数据. 优点:只需要设置一个json文件,就可以实现基本的添加功能,可以视为是零代码. 添加数据的服务实现的功能: 1 ...

  3. node.js+mysql环境搭建

    https://www.jianshu.com/p/9b338095cbe8 node.js+mysql环境搭建 0x01 前言 随着html web技术的发展,和全栈式开发的需求,对于前端人员来讲, ...

  4. Node.js NPM Package.json

    章节 Node.js NPM 介绍 Node.js NPM 作用 Node.js NPM 包(Package) Node.js NPM 管理包 Node.js NPM Package.json Nod ...

  5. Node.js实操练习(一)之Node.js+MySQL+RESTful

    前言 最近学习了一下node.js相关的内容,在这里初步做个小总结,说实话关于本篇博客的相关内容,自己很久之前就已经有过学习,但是你懂的,“好记性不如烂笔筒”,学过的东西不做笔记的话,很容易就会忘记的 ...

  6. Ubuntu 16.04 下部署Node.js+MySQL微信小程序商城

    转载于这篇文章 关于pm2看这篇文章 最近在研究小程序,申请了域名之后,再一次来配置环境,根据作者的步骤基本上完成了网站的架构,但由于环境路径等不同,配置上会有所不同,因此记录下来. 1.更新系统和安 ...

  7. node.js+mysql用户的注册登录验证

    下面代码实现的功能是:用node.js连接mysql实现用户的注册和登录,这里主要实现的是后端的验证代码,前端显示部分没具体写出. 整个程序的流程是这样的: 1.首先建立数据库reji,数据表user ...

  8. Node.js学习笔记——Node.js开发Web后台服务

    一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...

  9. 笔记-Node.js中的核心API之HTTP

    最近正在学习Node,在图书馆借了基本关于Node的书,同时在网上查阅资料,颇有收获,但是整体感觉对Node的理解还是停留在一个很模棱两可的状态.比如Node中的模块,平时练习就接触到那么几个,其他的 ...

随机推荐

  1. js精要之继承

    // 继承object.prototype的方法 // hasOwnProperty() //检查是否存在一个给定名字的自有属性 // propertyIsEnumerable() // 检查一个自有 ...

  2. DOM遍历

    前面的话 DOM遍历模块定义了用于辅助完成顺序遍历DOM结构的类型:Nodeiterator和TreeWalker,它们能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作. ...

  3. Linux驱动技术(四) _异步通知技术

    异步通知的全称是"信号驱动的异步IO",通过"信号"的方式,放期望获取的资源可用时,驱动会主动通知指定的应用程序,和应用层的"信号"相对应, ...

  4. 使用vlmcsd自建KMS服务~一句命令激活windows/office

    服务作用:在线激活windows和office 适用对象:VOL版本的windows和office 适用版本:截止到win10和office2016的所有版本 服务时间:24H,偶尔更新维护 优点:在 ...

  5. (3)activiti流程的挂起和激活

    有时候,我们需要对一个已经执行的流程进行暂停,而不是删除它,这个时候就需要我们调用activiti暂停和激活的api来操作他们 每启动一个流程实例,都会在该流程实例下产生相应的流程任务,处于1*多的关 ...

  6. 计算机程序的思维逻辑 (66) - 理解synchronized

    上节我们提到了多线程共享内存的两个问题,一个是竞态条件,另一个是内存可见性,我们提到,解决这两个问题的一个方案是使用synchronized关键字,本节就来讨论这个关键字. 用法 synchroniz ...

  7. Spring的bean管理(注解)

    前端时间总是用配置文件  内容太多 下面认识一下注解 注解是什么? 1代码里面的特殊标记,使用注解可以完成功能 2注解写法@XXX 3使用注解可以少些很多配置文件 Spring注解开发准备 注解创建准 ...

  8. Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core

    本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core --- ...

  9. 获取div滚动条的宽度

    获取滚动条的宽度: function getScrollWidth() { var noScroll, scroll, oDiv = document.createElement('div'); oD ...

  10. C语言对齐

    "%-md":左对齐,若m比实际少时,按实际输出.(m为整数) "%md":右对齐,若m比实际少时,按实际输出. 我自己编了一个,给你看看实际效果: #incl ...