jQuery zTree搜索-關(guān)鍵字查詢 遞歸無限層功能實(shí)現(xiàn)代碼
嘮叨一哈
前兩天朋友跟我說要一個(gè)ztree的搜索功能,我劈頭就是一巴掌:這種方法難道無數(shù)前輩還做少了?自己去找,我很忙~然后我默默地蹲著寫zTree的搜索方法去了。為什么呢?因?yàn)槲艺f了句“找不到是不可能的啊,肯定有很多人早做了無數(shù)了,找不到我給你寫還請(qǐng)你恰午飯”,然而我也去找了很久也沒有找到(淚崩,我的計(jì)劃,我的午飯~)。絕大多數(shù)都是用的API里面的getNodesByParamFuzzy()或者高亮之類的。然而朋友表示需求不符合:1. 匹配失敗父節(jié)點(diǎn)也隱藏;2.能自定義匹配規(guī)則,即能匹配name還能匹配屬性......(反正就是我想要的不是辣個(gè),小生臉上笑嘻嘻,心里.......那我給你寫唄~),下面進(jìn)入正文:
思維導(dǎo)圖

一般搜索功能只是在“既定范圍內(nèi)(方便稱呼)”匹配關(guān)鍵字,“既定范圍”即我們已經(jīng)知道搜索的范圍:比如說一個(gè)文本庫,一個(gè)下拉框,換而言之我們匹配的對(duì)象集大小已經(jīng)確定了。然而這一點(diǎn)在ztree上不可行,為什么呢?在我考慮了一下ztree搜索功能實(shí)現(xiàn)邏輯的時(shí)候問了一句:那啥,這棵樹的層級(jí)是固定的嗎?還是說不確定有多少層?老哥看著我會(huì)心一笑:你按無限層來寫~小生小腿肚子一抽。。因?yàn)闃涞膶蛹?jí)不確定,所以搜索范圍不確定,舉個(gè)栗子:目標(biāo)節(jié)點(diǎn)匹配成功,如果這個(gè)節(jié)點(diǎn)是子節(jié)點(diǎn),那么它的父節(jié)點(diǎn)也應(yīng)該是顯示的,然后它父節(jié)點(diǎn)的父節(jié)點(diǎn)也應(yīng)該是顯示的,然后它父節(jié)點(diǎn)的父節(jié)點(diǎn)的父節(jié)點(diǎn)的...Orz...這仿佛永遠(yuǎn)寫不到盡頭了...沒辦法,只能:遞歸,找到目標(biāo)節(jié)點(diǎn)的所有父節(jié)點(diǎn)和子節(jié)點(diǎn)。
邏輯關(guān)鍵點(diǎn)
在上面的思維導(dǎo)圖中我大致列出了邏輯,目標(biāo)節(jié)點(diǎn)在什么情況下顯示,什么情況下隱藏,這是我們必須清楚的關(guān)鍵點(diǎn),下面我們具體看下目標(biāo)節(jié)點(diǎn)存在的情況:

到了這里,相信對(duì)于如何實(shí)現(xiàn)滿足我們需求的搜索功能開發(fā),已經(jīng)能做到了然于心了,剩下的只是實(shí)現(xiàn)的方法,然而這完全不是事~(小生竊以為真正讓人憂心的理不清功能的流程,至于實(shí)現(xiàn)方法你們都懂的吧?0.0..)
關(guān)于樹節(jié)點(diǎn)
要完成上述流程中各種方法,我們需要知道樹節(jié)點(diǎn)的一系列屬性,我們都知道有api這種神器,然而api有一個(gè)特點(diǎn)就是齊全(齊全得我們想精確的找到某一個(gè)屬性或者方法時(shí)可能得一頓好找),這里我們想要的是如何快速得到自己想要的屬性或者方法,我們?cè)诳刂婆_(tái)打印出樹節(jié)點(diǎn)集合:
var treeObj=$.fn.zTree.getZTreeObj("homeTree"); // 設(shè)置根節(jié)點(diǎn)
var node = treeObj.getNodes(); // 獲取根節(jié)點(diǎn)
var nodes = treeObj.transformToArray(node); // 獲取所有節(jié)點(diǎn)
console.log(nodes);
看圖:我們能看到所有節(jié)點(diǎn),其中有id,name等各種屬性

再看圖:我們能看到任意節(jié)點(diǎn)的各種屬性,有我們想要的子節(jié)點(diǎn)集合 childern,父節(jié)點(diǎn)屬性 isParent ,節(jié)點(diǎn)id tId,父節(jié)點(diǎn)id parentTid...

萬事俱備,動(dòng)手
下面看一下相關(guān)方法,很多小細(xì)節(jié)需要在真正編碼過程中才能發(fā)現(xiàn),這里為了方便展示就直接列舉方法了。
聲明備用數(shù)組:
// 地區(qū)搜索 var parentArray = []; var childArray = [];
遞歸獲取目標(biāo)節(jié)點(diǎn)父節(jié)點(diǎn)集合:
// 遞歸獲取目標(biāo)節(jié)點(diǎn)所有父節(jié)點(diǎn)
function getParentsNode(treeNode){
var thisParentNode = treeNode.getParentNode(); //得到該節(jié)點(diǎn)的父節(jié)點(diǎn)
if( thisParentNode != null ){ // 父節(jié)點(diǎn)存在
parentArray.push(thisParentNode); // 儲(chǔ)存至數(shù)組
getParentsNode(thisParentNode); // 重調(diào)
}else{
return false;
}
}
遞歸獲取目標(biāo)節(jié)點(diǎn)子節(jié)點(diǎn)集合:
// 遞歸獲取目標(biāo)節(jié)點(diǎn)所有子節(jié)點(diǎn)
function getChildrenNode(treeNode){
var thisIsParent = treeNode.isParent; // 獲取目標(biāo)節(jié)點(diǎn) isParent 屬性,判斷是否為父節(jié)點(diǎn)
if( thisIsParent == true ){
var thisChildrenNode = treeNode.children; // 得到該節(jié)點(diǎn)的子節(jié)點(diǎn)集合
for(var i=0;i<thisChildrenNode.length;i++){
childArray.push(thisChildrenNode[i]); // 將該子節(jié)點(diǎn)加入數(shù)組中
getChildrenNode(thisChildrenNode[i]); // 重調(diào)
}
}else{
return false;
}
}
這里建議將匹配節(jié)點(diǎn)部分摘出來單獨(dú)寫一個(gè)方法,方便進(jìn)行拓展匹配規(guī)則,這里我們假設(shè)除了匹配name還需要匹配節(jié)點(diǎn)的 entity_code 屬性:
//匹配節(jié)點(diǎn)
function matchNode(treeNode,num){
var inputArea = $("input[name='searchArea']");
var name = treeNode.name;
var entityCode = treeNode.entity_code|| '';
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;
}
節(jié)點(diǎn)匹配成功方法:
// 節(jié)點(diǎn)匹配成功
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();
}
}
節(jié)點(diǎn)匹配失敗方法:
// 節(jié)點(diǎn)匹配失敗
function checkFalseArray(arr,treeNode){
var result = [];
var result2 = [];
var thisTid = treeNode.tId;
var thisLi = $("#"+thisTid);
var val = inputArea.val(); // 獲取檢索值
var thisParent = treeNode.getParentNode(); // 獲取目標(biāo)節(jié)點(diǎn)父節(jié)點(diǎn)
if( thisParent != null ){ // 有父節(jié)點(diǎn)
var thisBrotherArr = treeNode.getParentNode().children; // 得到包含自身的兄弟數(shù)組
for(var m=0;m<arr.length;m++){ // 匹配父節(jié)點(diǎn)
var num = matchNode(arr[m]);
if( num != -1 ){
result.push(arr[m]);
}
}
var resultLength = result.length;
for( var m=0;m<thisBrotherArr.length;m++ ){ // 匹配兄弟節(jié)點(diǎn)
var num = matchNode(thisBrotherArr[m]);
if( num != -1 ){
result2.push(thisBrotherArr[m]);
}
}
var resultLength2 = result2.length;
// 對(duì)于自身匹配失敗的節(jié)點(diǎn),要顯示必須滿足有父節(jié)點(diǎn)匹配成功,且兄弟級(jí)節(jié)點(diǎn)都匹配失敗
if( (resultLength == 0 && resultLength2 == 0) || resultLength2 != 0 ){
thisLi.hide();
}
if( resultLength !=0 && resultLength2 == 0 ){
thisLi.show();
}
}else{
thisLi.hide();
}
}
目標(biāo)節(jié)點(diǎn)匹配失敗 目標(biāo)節(jié)點(diǎn)即有父節(jié)點(diǎn)又有子節(jié)點(diǎn):
// 目標(biāo)節(jié)點(diǎn)匹配失敗 目標(biāo)節(jié)點(diǎn)即有父節(jié)點(diǎn)又有子節(jié)點(diǎn)
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++){ // 匹配子節(jié)點(diǎn)或父節(jié)點(diǎn)
var num = matchNode(arr[m]);
if( num != -1 ){
result.push(arr[m]); // 匹配成功儲(chǔ)存至數(shù)組
}
}
var resultLength = result.length; // 獲取匹配成功后返回的數(shù)組長(zhǎng)度
for(var m=0;m<arr2.length;m++){ // 匹配子節(jié)點(diǎn)或父節(jié)點(diǎn)
var num = matchNode(arr2[m]);
if( num != -1 ){
result2.push(arr2[m]); // 匹配成功儲(chǔ)存至數(shù)組
}
}
var resultLength2 = result2.length; // 獲取匹配成功后返回的數(shù)組長(zhǎng)度
if( resultLength == 0 && resultLength2 == 0 ){ // 子節(jié)點(diǎn)和父節(jié)點(diǎn)都匹配失敗
thisLi.hide();
}else{
thisLi.show(); // 有一種匹配成功或都匹配成功
}
}
定義搜索方法:
function searchArea(treeId, treeNode){ // 定義搜索方法
var inputArea = $("input[name='searchArea']");
var val = inputArea.val(); // 獲取檢索值
var treeObj=$.fn.zTree.getZTreeObj("homeTree"); // 設(shè)置根節(jié)點(diǎn)
var node = treeObj.getNodes(); // 獲取根節(jié)點(diǎn)
var nodes = treeObj.transformToArray(node); // 獲取所有節(jié)點(diǎn)
console.log(nodes);
for(var i=0;i<nodes.length;i++){
var thisNodePid = nodes[i].pId;
var thisParentNode =
parentArray = [];
childArray = [];
getParentsNode(nodes[i]); // 獲取目標(biāo)節(jié)點(diǎn)所有父節(jié)點(diǎn) 返回?cái)?shù)組
getChildrenNode(nodes[i]); // 獲取目標(biāo)節(jié)點(diǎn)所有子節(jié)點(diǎn) 返回?cái)?shù)組
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]);
}
}
}
}
調(diào)用搜索方法:
// 調(diào)用搜索方法
$(".searchAreaBtn").click(function(treeId, treeNode){
searchArea(treeId, treeNode);
});
var inputArea = $("input[name='searchArea']");
inputArea.keyup(function(treeId, treeNode,e){
var e = event || window.event;
var val = inputArea.val();
if( e.keyCode == 13 || val == "" ){
searchArea(treeId, treeNode);
}
});
看效果(電腦ps出問題了,用美圖秀秀拼的圖~囧...):

結(jié)語
理論上來說應(yīng)該是能支持無限層的,最多試了四層,沒有問題,沒有做更多測(cè)試,有興趣的看官可以試試,需要demo的可以留言,互相學(xué)習(xí),一起進(jìn)步,么么噠~
總結(jié)
以上所述是小編給大家介紹的jQuery zTree搜索-關(guān)鍵字查詢 遞歸無限層功能實(shí)現(xiàn)代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- jQuery插件select2利用ajax高效查詢大數(shù)據(jù)列表(可搜索、可分頁)
- 基于jquery實(shí)現(xiàn)的類似百度搜索的輸入框自動(dòng)完成功能
- 基于jquery的仿百度搜索框效果代碼
- 基于jQuery實(shí)現(xiàn)搜索關(guān)鍵字自動(dòng)匹配功能
- Jquery實(shí)現(xiàn)搜索框提示功能示例代碼
- 基于jQuery實(shí)現(xiàn)頁面搜索功能
- jQuery實(shí)現(xiàn)模糊查詢的方法分析
- jQuery+Ajax實(shí)現(xiàn)限制查詢間隔的方法
- 基于jquery的表格排序
- jQuery利用sort對(duì)DOM元素進(jìn)行排序操作
- jQuery實(shí)現(xiàn)條件搜索查詢、實(shí)時(shí)取值及升降序排序的方法分析
相關(guān)文章
jquery ajax請(qǐng)求實(shí)例深入解析
jquery中封裝了一些ajax請(qǐng)求的方法,很實(shí)用,本文將以此引入一個(gè)實(shí)例,對(duì)jquery中ajax請(qǐng)求的方法進(jìn)行詳細(xì)介紹,需要了解更多的朋友可以參考下2012-11-11
js實(shí)現(xiàn)的黑背景灰色二級(jí)導(dǎo)航菜單效果代碼
這篇文章主要介紹了js實(shí)現(xiàn)的黑背景灰色二級(jí)導(dǎo)航菜單效果代碼,涉及javascript操作頁面元素動(dòng)態(tài)切換的實(shí)現(xiàn)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-08-08
JQuery 構(gòu)建客戶/服務(wù)分離的鏈接模型中Table中的排序分析
從上篇文章,我們實(shí)現(xiàn)了Table分頁代碼的高效性,咱們繼續(xù)沿著這個(gè)思路,探討Table表格數(shù)據(jù)中另外一個(gè)很常見的排序問題。說到排序,我記得在asp.net中 GridView中提供了這樣的方便,只需在展示字段上加上 Sorting 這樣的屬性,基本就完成了,剩下就是服務(wù)端cs代碼的寫法了。2010-01-01
jQuery 順便學(xué)習(xí)下CSS選擇器 奇偶匹配nth-child(even)
今天學(xué)習(xí)jQuery,看到nth-child(even)用法,特意找了下這個(gè)選擇器的用法,在CSS3標(biāo)準(zhǔn)中,用法很強(qiáng)大。2010-05-05
jQuery實(shí)現(xiàn)電梯導(dǎo)航模塊
這篇文章主要為大家詳細(xì)介紹了jQuery實(shí)現(xiàn)電梯導(dǎo)航模塊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
jQuery實(shí)現(xiàn)的checkbox級(jí)聯(lián)選擇下拉菜單效果示例
這篇文章主要介紹了jQuery實(shí)現(xiàn)的checkbox級(jí)聯(lián)選擇下拉菜單效果,涉及jQuery鼠標(biāo)事件響應(yīng)及表格table動(dòng)態(tài)操作的相關(guān)技巧,需要的朋友可以參考下2016-12-12

