最近刚走出校园的我找到了第一份工作,在入职考核中就遇见了一道Z-tree的试题

这道题目本身是不难的,但是我第一次接触这个插件而且还把解决问题的方向搞错了,弄的我好几天都很难受。

弄得我都开始怀疑人生,甚至开始怀疑自己是否适合做编程。

为了纪念这个 恶心了我好几天的试题 我决定谨以此篇纪念我无处安放的青春

题目要求

要求从后台的数据库里面把一个公司部门和员工的信息用Z-tree显示出来(这个很简单!)

并且每一个父节点都要显示下方叶子节点的个数,最顶层的根结点的显示的数量要由下方的子父节点统计的数量累计和一致

(PS.不管多深都要显示的正确的)

我呢,开始以为这些叶子节点的数量是用SQL语句查出来的

就拼命的去用sql的函数去写递归,但是总是说我的返回结果字段太长,就因为这样我钻了牛角尖

下面说一下正解

我用的数据库里是有两张表的 一张是department部门的关系表    另一张是  users 一个员工的信息表

员工信息表的内容是和 部门表有对应的字段的

表的具体内容我就不列出来了

下面我来具体说一说如何用递归的方法查出来叶子节点的数量的吧

思路呢 是这样的

我们要先获取到 Ztree的所有子节点 然后逐级进行遍历统计

核心代码如下:

这个是有回调函数的那种(不是一次性计算完),效果就是你每点开一级父文件才会统计下面的叶子节点数

$(function(){//页面加载完成
ajaxFun();
}); function ajaxFun(){
$.ajax({
url:"index.php",//连接后台的地址
type:"post",//定义数据的传输方式
data:{
type:'get_date'
},//向后台发送的数据
success:function(data){//连接成功后接收后台的数据
$all_data = eval(data);//接收后台数据
console.log($all_data);
var setting = {
callback: {
onExpand: expandNode,//节点被展开时计算子节点下的叶子节点的数目
},
data: { simpleData: {
enable: true,
}
}, }; $data1=$all_data[0];//部门关系
$data2=$all_data[1];//人员所属的 部门 以及组
var zNodes =[];//定义zNodes json数组 组织数据
for(var i in $data1){//填充部门数据
var flag = false;
zNodes.push({id:$data1[i].code, pId:$data1[i].father_code, name:$data1[i].name+"(0)",isParent:true});
} for(var i in $data2){//填充人员数据
zNodes.push({id:$data2[i].userid, pId:$data2[i].father_code, name:$data2[i].username});
}
//console.log(zNodes);
$.fn.zTree.init($("#treeDemo"), setting, zNodes);//加载Z-tree
initNodeNum(); //调用第一次页面加载完成计算最上层节点下所有子节点的方法
} });
} function initNodeNum(){ var zTree = $.fn.zTree.getZTreeObj("treeDemo");//获取加载后的z-tree对象
var nodes = zTree.getNodes();//获取 zTree 的全部节点数据
for (var i=0, l=nodes.length; i < l; i++)//遍历节点数据
{
var nodeId = nodes[i].id;//记录节点id
var nodeName = nodes[i].name;//记录节点名称
var isParent = nodes[i].isParent;//记录节点是否是父
var pId = nodes[i].pId;//记录节点父id
if(isParent&&pId ==null){//如果是父节点并且Pid是空
var childArr =[];//定义数组存放子节点
childArr = getAllChildrenNodes(nodes[i],childArr);
var str = nodeName.substring(0,nodeName.length-2);//去掉括号
var newname = str+childArr.length+')';//计算上节点数并加上括号
nodes[i].name = newname;//重新命名
zTree.updateNode(nodes[i]);//并更新节点信息
} } } function getAllChildrenNodes(treeNode, result) {//给定一个节点对象
if (treeNode.isParent) {//如果是父
var childrenNodes = treeNode.children;
if (childrenNodes) {
for (var i = 0; i < childrenNodes.length; i++) {
if (!childrenNodes[i].isParent){ //只要叶子节点
result.push(childrenNodes[i].id);
}
result = getAllChildrenNodes(childrenNodes[i], result);
}
}
}
return result;
}
function expandNode(event, treeId, treeNode) { var zTree = $.fn.zTree.getZTreeObj("treeDemo"); if (treeNode.isParent) {
var childrenNodes = treeNode.children;
if (childrenNodes) {
for (var i = 0; i < childrenNodes.length; i++) {
if(!childrenNodes[i].isParent)continue;
var nodeName = childrenNodes[i].name;
var childArr =[];
childArr = getAllChildrenNodes(childrenNodes[i],childArr);
var str = nodeName.substring(0,nodeName.length-2);
var newname = str+childArr.length+')';
childrenNodes[i].name = newname;
zTree.updateNode(childrenNodes[i]);
}
}
} }

还有一种是没有回调的那种的,这种是一次性计算出来的,比较符合线上的需求

代码如下:

 $(function(){//页面加载完成
ajaxFun();
}); function ajaxFun(){
$.ajax({
url:"index.php",//连接后台的地址
type:"post",//定义数据的传输方式
data:{
type:'get_date'
},//向后台发送的数据
success:function(data){//连接成功后接收后台的数据
$all_data = eval(data);//接收后台数据
console.log($all_data);
var setting = {
callback: {
//取消回调函数
},
data: { simpleData: {
enable: true,
}
}, }; $data1=$all_data[0];//部门关系
$data2=$all_data[1];//人员所属的 部门 以及组
var zNodes =[];//定义zNodes json数组 组织数据
for(var i in $data1){//填充部门数据
var flag = false;
zNodes.push({id:$data1[i].code, pId:$data1[i].father_code, name:$data1[i].name+"(0)",isParent:true});
} for(var i in $data2){//填充人员数据
zNodes.push({id:$data2[i].userid, pId:$data2[i].father_code, name:$data2[i].username});
}
//console.log(zNodes);
$.fn.zTree.init($("#treeDemo"), setting, zNodes);//加载Z-tree
initNodeNum(); //调用第一次页面加载完成计算最上层节点下所有子节点的方法
} });
} function initNodeNum(){ var zTree = $.fn.zTree.getZTreeObj("treeDemo");//获取加载后的z-tree对象
var nodes = zTree.getNodes();//获取 zTree 当前显示的节点数据
var nodess = zTree.transformToArray(nodes)//获取所有节点
for (var i=0, l=nodess.length; i < l; i++)//遍历节点数据
{
var nodeId = nodess[i].id;//记录节点id
var nodeName = nodess[i].name;//记录节点名称
var isParent = nodess[i].isParent;//记录节点是否是父
var pId = nodess[i].pId;//记录节点父id
if(isParent){//如果是父节点
var childArr =[];//定义数组存放子节点
childArr = getAllChildrenNodes(nodess[i],childArr);//在这里去循环调用计算子节点的方法
var str = nodeName.substring(0,nodeName.length-2);//去掉括号
var newname = str+childArr.length+')';//计算上节点数并加上括号
nodess[i].name = newname;//重新命名
zTree.updateNode(nodess[i]);//并更新节点信息
} } }
//这个方法就是递归没跑了
//就是 给定一个节点对象 和返回结果的变量(我这里用的是数组)
//就会将这个父节点下面的所有的叶子节点的id记录到一个数组当中
//直到没有父节点了,返回后我们可以计算这个数组的长度就可以知道这个
//父级节点下到底有多少个叶子节点了
function getAllChildrenNodes(treeNode, result) {//给定一个节点对象
if (treeNode.isParent) {//如果是父
var childrenNodes = treeNode.children;
if (childrenNodes) {
for (var i = 0; i < childrenNodes.length; i++) {
if (!childrenNodes[i].isParent){ //只要叶子节点
result.push(childrenNodes[i].id);
}
result = getAllChildrenNodes(childrenNodes[i], result);
}
}
}
return result;
}     //这个是之前的不用的回调了,就先放在这里了
function expandNode(event, treeId, treeNode) { var zTree = $.fn.zTree.getZTreeObj("treeDemo"); if (treeNode.isParent) {
var childrenNodes = treeNode.children;
if (childrenNodes) {
for (var i = 0; i < childrenNodes.length; i++) {
if(!childrenNodes[i].isParent)continue;
var nodeName = childrenNodes[i].name;
var childArr =[];
childArr = getAllChildrenNodes(childrenNodes[i],childArr);
var str = nodeName.substring(0,nodeName.length-2);
var newname = str+childArr.length+')';
childrenNodes[i].name = newname;
zTree.updateNode(childrenNodes[i]);
}
}
} }

好了我的分享到这里了 ,有疑问 的小伙伴可以私信我,我们可以一起探讨!!!

Z-tree 统计每一父节点的叶子节点数(看这一篇就够了)的更多相关文章

  1. Jquery EasyUI Combotree只能选择叶子节点且叶子节点有多选框

    Jquery EasyUI Combotree只能选择叶子节点且叶子节点有多选框 Jquery EasyUI Combotree单选框,Jquery EasyUI Combotree只能选择叶子节点 ...

  2. MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其下属的所有子节点(包含路径上的枝干节点和叶子节点) 枝干节点:如果一个节点下还有子节点,则为枝干节点. 叶子节点:如果一个节点下不再有子节点 ...

  3. 找出所有从根节点到叶子节点路径和等于n的路径并输出

    //找出所有从根节点到叶子节点路径和等于n的路径并输出 Stack<Node> stack = new Stack<Node>(); public void findPath( ...

  4. 求二叉树的深度,从根节点到叶子节点的最大值,以及最大路径(python代码实现)

    首先定义一个节点类,包含三个成员变量,分别是节点值,左指针,右指针,如下代码所示: class Node(object): def __init__(self, value): self.value ...

  5. Ext.jsTree 向子节点添加叶子节点

    // 定义搜索节点树结构Store const nodeStore = Ext.create('Ext.data.TreeStore', { autoLoad : true, id : 'nodeSt ...

  6. 根节点到叶子节点路径之和为target

    //递归吧,但是在递归到底的条件上要判断好,比如说完整路径是到叶子节点,也就是说左右子节点都为空,并且这时候的root.val==target表示找到了一个list,再返回. 但是因为我并没有直接就用 ...

  7. easyui tree 判断是否是叶子节点

    <input class="add" id="add" style="display: none" type="submit ...

  8. hdu 2196 叶子节点最长距离(树DP)

    http://www.cnblogs.com/kuangbin/archive/2012/08/28/2659915.html 求每个节点到叶子节点的最长距离 需要保存每个节点到叶子节点距离的最大值和 ...

  9. LC: 404.左叶子节点

    计算给定二叉树的所有左叶子之和. 示例: / \ 9 20 / \ 15 7 ,所以返回 24 解析 我们需要找到这样的节点 属于叶子节点 属于父节点的左子节点 方法一:用栈,dfs遍历,用全局变量r ...

随机推荐

  1. CMMI的5个级别

    为了帮助软件企业对软件工程过程进行管理和改进,增强开发与改进能力,从而能按时地.不超预算地开发出高质量的软件,美国国防部与卡内基-梅隆大学和美国国防工业协会共同开发和研制了CMMI(软件能力成熟度模型 ...

  2. linux C 线程池(物不可穷也~)

    Linux 多线程编程之 线程池 的原理和一个简单的C实现,提高对多线程编 程的认知,同步处理等操作,以及如何在实际项目中高效的利用多线程开 发. 1.  线程池介绍 为什么需要线程池??? 目前的大 ...

  3. grafana查询中的变量templating

    有时我们在管理成百上千台机器的时候,配置grafana无疑是明智的,因为你不需要一个一个的把每个机器的图形都配置一遍,利用templating就可以瞬间实现n台机器的状态显示了. templating ...

  4. SWIFT Function

    Swift中的函数跟JAVA语言的函数差不多,但也有差别,SWIFT中定义函数可以指定参数的名称这也是别的语言没有的,好处就是增加了可读性.其返回值是放在未尾的,如以下定义一个加法器: func ad ...

  5. 算法训练 Lift and Throw

    算法训练 Lift and Throw   时间限制:3.0s   内存限制:256.0MB      问题描述 给定一条标有整点(1, 2, 3, ...)的射线. 定义两个点之间的距离为其下标之差 ...

  6. ping命令技巧详解 windows下ping命令知识大全

    windows ping命令对于多数电脑爱好者都不会陌生,通过ping ip可以知道网络是否畅通或者网络传输质量如何等,是网络技术人员常用的检测网络命令,多数朋友对ping命令知道的并不多,接下来本文 ...

  7. ubuntu下设置电脑为WiFi热点

    这是个问题 自从Windows奔溃以来! 扔掉360:Linux下无线网卡作WiFi路由器

  8. SYSTEM\sys\sys.c:33:7: error: expected '(' before 'void' __ASM void MSR_MSP(u32 addr)

    在STM32中的sys.c文件编译报出这个错误时: __ASM void MSR_MSP(u32 addr){ MSR MSP, r0 //set Main Stack value BX r14} 如 ...

  9. STM32 RTC时钟的配置

    1) 使能电源时钟和备份区域时钟. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能电源时钟和 ...

  10. HihoCoder - 1886 :中位数2(贪心)

    描述 对于一个长度为n的数列A,我们如下定义A的中位数med(A): 当n是奇数时,A的中位数是第(n+1)/2大的数:当n是偶数时,A的中位数是第n/2大的数和第n/2+1大的数的平均值. 同时,我 ...