首頁  >  文章  >  web前端  >  jQuery實作遞歸無限層功能

jQuery實作遞歸無限層功能

亚连
亚连原創
2018-06-09 14:51:371508瀏覽

這篇文章主要介紹了zTree搜尋功能-- 關鍵字查詢-- 遞歸無限層的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

 嘮叨一哈

  前兩天朋友跟我說要一個ztree的搜尋功能,我劈頭就是一巴掌:這種方法難道無數前輩還做少了?自己去找,我很忙~然後我默默地蹲著寫zTree的搜尋方法去了。為什麼呢?因為我說了句“找不到是不可能的啊,肯定有很多人早做了無數了,找不到我給你寫還請你恰午飯”,然而我也去找了很久也沒有找到(淚崩,我的計劃,我的午餐~)。絕大多數都是用的API裡面的getNodesByParamFuzzy()或是高亮之類的。然而朋友表示需求不符合:1. 匹配失敗父節點也隱藏;2.能自訂匹配規則,即能匹配name還能匹配屬性......(反正就是我想要的不是辣個,小生臉上笑嘻嘻,心裡.......那我給你寫唄~),下面進入正文:

心智圖

  

  一般搜尋功能只是在「既定範圍內(方便稱呼)」符合關鍵字,「既定範圍」即我們已經知道搜尋的範圍:比如說一個文字庫,一個下拉框,換而言之我們匹配的物件集大小已經確定了。然而這一點在ztree上不可行,為什麼呢?在我考慮了一下ztree搜尋功能實現邏輯的時候問了一句:那啥,這棵樹的層級是固定的嗎?還是說不確定有多少層?老哥看我會心一笑:你按無限層來寫~小生小腿肚子一抽。 。因為樹的層級不確定,所以搜尋範圍不確定,舉個栗子:目標節點匹配成功,如果這個節點是子節點,那麼它的父節點也應該是顯示的,然後它父節點的父節點也應該是顯示的,然後它父節點的父節點的父節點的...Orz...這彷彿永遠寫不到盡頭了...沒辦法,只能:遞歸,找到目標節點的所有父節點和子節點。

邏輯關鍵點

  在上面的心智圖中我大致列出了邏輯,目標節點在什麼情況下顯示,什麼情況下隱藏,這是我們必須清楚的關鍵點,下面我們具體看下目標節點存在的情況:

  

  到了這裡,相信對於如何實現滿足我們需求的搜尋功能開發,已經能做到了然於心了,剩下的只是實現的方法,然而這完全不是事~(小生竊以為真正讓人憂心的理不清功能的流程,至於實現方法你們都懂的吧?0.0..)

關於樹節點

#  要完成上述流程中各種方法,我們需要知道樹節點的一系列屬性,我們都知道有api這種神器,然而api有一個特點就是齊全(齊全得我們想精確的找到某一個屬性或者方法時可能得一頓好找),這裡我們想要的是如何快速得到自己想要的屬性或方法,我們在控制台列印出樹節點集合: 

 var treeObj=$.fn.zTree.getZTreeObj("homeTree"); // 设置根节点
  var node = treeObj.getNodes(); // 获取根节点
  var nodes = treeObj.transformToArray(node); // 获取所有节点
  console.log(nodes);

   看圖:我們能看到所有節點,其中有id,name等各種屬性

#  再看圖:我們能看到任意節點的各種屬性,有我們想要的子節點集合childern,父節點屬性isParent ,節點id tId,父節點id parentTid...

萬事俱備,動手

  下面看一下相關方法,很多小細節需要在真正編碼過程中才能發現,這裡為了方便展示就直接列舉方法了。

  宣告備用數組:

// 地区搜索
 var parentArray = [];
 var childArray = [];

   遞歸取得目標節點父節點集合:

 // 递归获取目标节点所有父节点
 function getParentsNode(treeNode){
  var thisParentNode = treeNode.getParentNode(); //得到该节点的父节点
  if( thisParentNode != null ){ // 父节点存在
   parentArray.push(thisParentNode); // 储存至数组
   getParentsNode(thisParentNode); // 重调 
  }else{
   return false;
  }   
 }

   遞歸取得目標節點子節點集合:

 // 递归获取目标节点所有子节点
 function getChildrenNode(treeNode){
  var thisIsParent = treeNode.isParent; // 获取目标节点 isParent 属性,判断是否为父节点
  if( thisIsParent == true ){
   var thisChildrenNode = treeNode.children; // 得到该节点的子节点集合
   for(var i=0;i<thisChildrenNode.length;i++){
    childArray.push(thisChildrenNode[i]); // 将该子节点加入数组中
    getChildrenNode(thisChildrenNode[i]); // 重调  
   }
  }else{
   return false;
  }
 }

   遞歸取得目標節點子節點集合:

 //匹配节点
 function matchNode(treeNode,num){
  var inputArea = $("input[name=&#39;searchArea&#39;]");
  var name = treeNode.name;
  var entityCode = treeNode.entity_code|| &#39;&#39;;
  var val = inputArea.val(); // 获取检索值
  var numName = name.indexOf(val);
  var numCode = entityCode.indexOf(val);
  var num = -1;
  if( numName != -1 || numCode !=-1 ){
   num = 1;
  }
  if( numName == -1 && numCode == -1 ){
   num = -1; 
  }
  return num;
 }

   這裡建議這裡建議將建議將匹配節點部分摘出來單獨寫一個方法,方便進行拓展匹配規則,這裡我們假設除了匹配name還需要匹配節點的entity_code 屬性:

 // 节点匹配成功
 function checkTrueArray(arr,treeNode){
  var thisTid = treeNode.tId;
  var thisLi = $("#"+thisTid);
  for(var n=0;n<arr.length;n++){
   var thisNodeId = arr[n].tId;
   var thisNodeLi = $("#"+thisNodeId);
   thisLi.show();
   thisNodeLi.show();
  }
 }

   節點匹配成功方法:

 // 节点匹配失败
 function checkFalseArray(arr,treeNode){
  var result = [];
  var result2 = [];
  var thisTid = treeNode.tId;
  var thisLi = $("#"+thisTid);
  var val = inputArea.val(); // 获取检索值
  var thisParent = treeNode.getParentNode(); // 获取目标节点父节点
  if( thisParent != null ){ // 有父节点
   var thisBrotherArr = treeNode.getParentNode().children; // 得到包含自身的兄弟数组
   for(var m=0;m<arr.length;m++){ // 匹配父节点
    var num = matchNode(arr[m]);
    if( num != -1 ){
     result.push(arr[m]);
    }
   }
   var resultLength = result.length;
   for( var m=0;m<thisBrotherArr.length;m++ ){ // 匹配兄弟节点
    var num = matchNode(thisBrotherArr[m]);
    if( num != -1 ){
     result2.push(thisBrotherArr[m]);
    }
   }
   var resultLength2 = result2.length;
   // 对于自身匹配失败的节点,要显示必须满足有父节点匹配成功,且兄弟级节点都匹配失败
   if( (resultLength == 0 && resultLength2 == 0) || resultLength2 != 0 ){
    thisLi.hide();
   }
   if( resultLength !=0 && resultLength2 == 0 ){
    thisLi.show();
   }
  }else{
   thisLi.hide();
  } 
 }

   節點匹配失敗方法:

 // 目标节点匹配失败 目标节点即有父节点又有子节点
 function checkAllArray(arr,arr2,treeNode){
  var result = [];
  var result2 = [];
  var thisTid = treeNode.tId;
  var thisLi = $("#"+thisTid);
  var val = inputArea.val(); // 获取检索值
  for(var m=0;m<arr.length;m++){ // 匹配子节点或父节点
   var num = matchNode(arr[m]);
   if( num != -1 ){
    result.push(arr[m]); // 匹配成功储存至数组
   }
  }
  var resultLength = result.length; // 获取匹配成功后返回的数组长度
  for(var m=0;m<arr2.length;m++){ // 匹配子节点或父节点
   var num = matchNode(arr2[m]);
   if( num != -1 ){
    result2.push(arr2[m]); // 匹配成功储存至数组
   }
  }
  var resultLength2 = result2.length; // 获取匹配成功后返回的数组长度
  if( resultLength == 0 && resultLength2 == 0 ){ // 子节点和父节点都匹配失败
   thisLi.hide();
  }else{ 
   thisLi.show(); // 有一种匹配成功或都匹配成功
  }
 }

    目標節點匹配失敗目標節點即有父節點又有子節點:

 function searchArea(treeId, treeNode){ // 定义搜索方法
  var inputArea = $("input[name=&#39;searchArea&#39;]");
  var val = inputArea.val(); // 获取检索值
  var treeObj=$.fn.zTree.getZTreeObj("homeTree"); // 设置根节点
  var node = treeObj.getNodes(); // 获取根节点
  var nodes = treeObj.transformToArray(node); // 获取所有节点
  console.log(nodes);
  for(var i=0;i<nodes.length;i++){
   var thisNodePid = nodes[i].pId;
   var thisParentNode = 
   parentArray = [];
   childArray = [];
   getParentsNode(nodes[i]); // 获取目标节点所有父节点 返回数组
   getChildrenNode(nodes[i]); // 获取目标节点所有子节点 返回数组
   var num = matchNode(nodes[i]);
   if( nodes[i].isParent == false ){ 
    if( num != -1 ){
     checkTrueArray(parentArray,nodes[i]);
    }else{
     checkFalseArray(parentArray,nodes[i]);
    }
   }
   if( nodes[i].isParent == true ){
    if( num != -1 ){
     checkTrueArray(parentArray,nodes[i]); 
     checkTrueArray(childArray,nodes[i]);     
    }else{
     checkAllArray(parentArray,childArray,nodes[i]);
    }
   }   
  }
  
 }

  定義搜尋方法:

 // 调用搜索方法
 $(".searchAreaBtn").click(function(treeId, treeNode){
  searchArea(treeId, treeNode);
 });
 var inputArea = $("input[name=&#39;searchArea&#39;]");
 inputArea.keyup(function(treeId, treeNode,e){
  var e = event || window.event;
  var val = inputArea.val();
  if( e.keyCode == 13 || val == "" ){
   searchArea(treeId, treeNode);
  }
 });

  呼叫搜尋方法:

rrreee###   看效果(電腦ps出問題了,用美圖秀拼的圖~囧...):###

結語

#  理論上應該是能支持無限層的,最多試了四層,沒有問題,沒有做更多測試,有興趣的看官可以試試,需要demo的可以留言,互相學習,一起進步

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

在Vue中如何實作表頭與首列固定

jquery.picsign中如何使用圖片標註元件

透過webpack如何打包koa2 框架app,該怎麼做?

以上是jQuery實作遞歸無限層功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn