最近剛走出校園的我找到了第一份工作,在入職考核中就遇見了一道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]); } } } }
還有一種是沒有回調的那種的,這種是一次性計算出來的,比較符合線上的需求
代碼如下:
1 $(function(){//頁面加載完成 2 ajaxFun(); 3 }); 4 5 function ajaxFun(){ 6 $.ajax({ 7 url:"index.php",//連接后台的地址 8 type:"post",//定義數據的傳輸方式 9 data:{ 10 type:'get_date' 11 },//向后台發送的數據 12 success:function(data){//連接成功后接收后台的數據 13 $all_data = eval(data);//接收后台數據 14 console.log($all_data); 15 var setting = { 16 callback: { 17 //取消回調函數 18 }, 19 data: { 20 21 simpleData: { 22 enable: true, 23 } 24 }, 25 26 }; 27 28 29 $data1=$all_data[0];//部門關系 30 $data2=$all_data[1];//人員所屬的 部門 以及組 31 var zNodes =[];//定義zNodes json數組 組織數據 32 for(var i in $data1){//填充部門數據 33 var flag = false; 34 zNodes.push({id:$data1[i].code, pId:$data1[i].father_code, name:$data1[i].name+"(0)",isParent:true}); 35 } 36 37 for(var i in $data2){//填充人員數據 38 zNodes.push({id:$data2[i].userid, pId:$data2[i].father_code, name:$data2[i].username}); 39 } 40 //console.log(zNodes); 41 $.fn.zTree.init($("#treeDemo"), setting, zNodes);//加載Z-tree 42 initNodeNum(); //調用第一次頁面加載完成計算最上層節點下所有子節點的方法 43 } 44 45 }); 46 } 47 48 function initNodeNum(){ 49 50 var zTree = $.fn.zTree.getZTreeObj("treeDemo");//獲取加載后的z-tree對象 51 var nodes = zTree.getNodes();//獲取 zTree 當前顯示的節點數據 52 var nodess = zTree.transformToArray(nodes)//獲取所有節點 53 for (var i=0, l=nodess.length; i < l; i++)//遍歷節點數據 54 { 55 var nodeId = nodess[i].id;//記錄節點id 56 var nodeName = nodess[i].name;//記錄節點名稱 57 var isParent = nodess[i].isParent;//記錄節點是否是父 58 var pId = nodess[i].pId;//記錄節點父id 59 if(isParent){//如果是父節點 60 var childArr =[];//定義數組存放子節點 61 childArr = getAllChildrenNodes(nodess[i],childArr);//在這里去循環調用計算子節點的方法 62 var str = nodeName.substring(0,nodeName.length-2);//去掉括號 63 var newname = str+childArr.length+')';//計算上節點數並加上括號 64 nodess[i].name = newname;//重新命名 65 zTree.updateNode(nodess[i]);//並更新節點信息 66 } 67 68 } 69 70 71 } 72 //這個方法就是遞歸沒跑了 73 //就是 給定一個節點對象 和返回結果的變量(我這里用的是數組) 74 //就會將這個父節點下面的所有的葉子節點的id記錄到一個數組當中 75 //直到沒有父節點了,返回后我們可以計算這個數組的長度就可以知道這個 76 //父級節點下到底有多少個葉子節點了 77 function getAllChildrenNodes(treeNode, result) {//給定一個節點對象 78 if (treeNode.isParent) {//如果是父 79 var childrenNodes = treeNode.children; 80 if (childrenNodes) { 81 for (var i = 0; i < childrenNodes.length; i++) { 82 if (!childrenNodes[i].isParent){ //只要葉子節點 83 result.push(childrenNodes[i].id); 84 } 85 result = getAllChildrenNodes(childrenNodes[i], result); 86 } 87 } 88 } 89 return result; 90 }
//這個是之前的不用的回調了,就先放在這里了 91 function expandNode(event, treeId, treeNode) { 92 93 var zTree = $.fn.zTree.getZTreeObj("treeDemo"); 94 95 if (treeNode.isParent) { 96 var childrenNodes = treeNode.children; 97 if (childrenNodes) { 98 for (var i = 0; i < childrenNodes.length; i++) { 99 if(!childrenNodes[i].isParent)continue; 100 var nodeName = childrenNodes[i].name; 101 var childArr =[]; 102 childArr = getAllChildrenNodes(childrenNodes[i],childArr); 103 var str = nodeName.substring(0,nodeName.length-2); 104 var newname = str+childArr.length+')'; 105 childrenNodes[i].name = newname; 106 zTree.updateNode(childrenNodes[i]); 107 } 108 } 109 } 110 111 }
好了我的分享到這里了 ,有疑問 的小伙伴可以私信我,我們可以一起探討!!!