菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)
初学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数据构建为树(递归制作树状菜单数据接口)的更多相关文章
- Node.js + MySQL 实现数据的增删改查
通过完成一个 todo 应用展示 Node.js + MySQL 增删改查的功能.这里后台使用 Koa 及其相应的一些中间件作为 server 提供服务. 初始化项目 $ mkdir node-cru ...
- 零代码第一步,做个添加数据的服务先。node.js + mysql
node.js + mysql 实现数据添加的功能.万事基于服务! 增删改查之添加数据. 优点:只需要设置一个json文件,就可以实现基本的添加功能,可以视为是零代码. 添加数据的服务实现的功能: 1 ...
- node.js+mysql环境搭建
https://www.jianshu.com/p/9b338095cbe8 node.js+mysql环境搭建 0x01 前言 随着html web技术的发展,和全栈式开发的需求,对于前端人员来讲, ...
- Node.js NPM Package.json
章节 Node.js NPM 介绍 Node.js NPM 作用 Node.js NPM 包(Package) Node.js NPM 管理包 Node.js NPM Package.json Nod ...
- Node.js实操练习(一)之Node.js+MySQL+RESTful
前言 最近学习了一下node.js相关的内容,在这里初步做个小总结,说实话关于本篇博客的相关内容,自己很久之前就已经有过学习,但是你懂的,“好记性不如烂笔筒”,学过的东西不做笔记的话,很容易就会忘记的 ...
- Ubuntu 16.04 下部署Node.js+MySQL微信小程序商城
转载于这篇文章 关于pm2看这篇文章 最近在研究小程序,申请了域名之后,再一次来配置环境,根据作者的步骤基本上完成了网站的架构,但由于环境路径等不同,配置上会有所不同,因此记录下来. 1.更新系统和安 ...
- node.js+mysql用户的注册登录验证
下面代码实现的功能是:用node.js连接mysql实现用户的注册和登录,这里主要实现的是后端的验证代码,前端显示部分没具体写出. 整个程序的流程是这样的: 1.首先建立数据库reji,数据表user ...
- Node.js学习笔记——Node.js开发Web后台服务
一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...
- 笔记-Node.js中的核心API之HTTP
最近正在学习Node,在图书馆借了基本关于Node的书,同时在网上查阅资料,颇有收获,但是整体感觉对Node的理解还是停留在一个很模棱两可的状态.比如Node中的模块,平时练习就接触到那么几个,其他的 ...
随机推荐
- python之FTP程序(支持多用户在线)
转发注明出处:http://www.cnblogs.com/0zcl/p/6259128.html 一.需求 1. 用户加密认证 (完成)2. 允许同时多用户登录 (完成)3. 每个用户有自己的家目录 ...
- MEAN教程1-MongoDB安装和使用
MEAN是MongoDB.Express.AngularJS和Node.js的缩写.其理念是仅使用JavaScript一种语言来驱动整个应用.其最鲜明的特点有以下几个:1整个应用只使用一种语言:2整个 ...
- 对于Java泛型的理解
源起:查看COLLECIOTNS类 Q1:为什么java需要泛型? 因为java对于对象类型的确认在编译期,那么强制类型转换就可以通过编译,但是运行时的错误却无法避免,那么泛型的存在可以避免强制类型转 ...
- 毕向东udp学习笔记3多线程聊天
项目功能: 实现了多线程下的发送接收,比较好 希望可以加入GUI,类似聊天软件一样,有一个消息输入框,捕获输入消息,作为发送线程 有一个显示消息框,接收消息并显示,作为接收线程 不知道的是,当在线程中 ...
- udp 双机通信(服务器循环检测)2
此文摘自:http://blog.csdn.net/qinpeng100423/article/details/8980423,谢谢了 自己上一篇写的udp通信,只能运行一次,参考了这位博主的,只是把 ...
- Swift3.0 中 Strings/Characters 闲聊
前言 本篇文章主要浅析字符串\字符在 Swift 和 Objective-C 之间的区别及其简单用法.如有不妥的地方还望大家及时帮忙纠正. 字符串判空 在 swift 语言中空字符串初始化方式常用的有 ...
- React实例----一个表单验证比较复杂的页面
前言:这阵子看了两本CSS的书~对于CSS层叠,定位,继承等机制基本上都了解了,就想着自己写几个页面~正好自己就写了写CSS样式,然后用React渲染出来~ 闲话不多说,简单说一说这个页面,希望能对大 ...
- JavaScript中国象棋程序(5) - Alpha-Beta搜索
"JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第5节. 这一系列共有9个部分: 0.JavaScript中国象 ...
- centos安装docker容器
centos安装docker容器 系统环境需求 docker要运行在centos7系统中,系统为64位机器上,内核最小版本在3.10以上 如果系统为centos6,后面有附带的安装方法 uname - ...
- 【排序算法】冒泡排序算法 Java实现
基本思想 设数组长度为N. 比较前后两个数据,如果前面的数据大于后面的数据,就将两个数据交换. 这样对数组的第0个数据到N - 1个数据进行遍历后,最大的一个数据就沉到了数组的第N - 1个位置. N ...
