最近項目用到樹型結構的交互,一開始並不打算選擇zTree,為了項目進度我妥協了,這一妥協后果就是我進坑了,在2天的掙扎中,我終於跳出坑了,活了下來,有一些感慨紀錄下來。
有一個業務場景需要2個樹型結構,一個初始化樹型結構,標示為左樹,另一個則是為選擇后生成的新樹結構,標示為右樹;
首先在左樹選擇要使用的數據,點擊新增在右樹展示所選的數據的新樹結構。
這個功能在jquery.zTree的API里面是沒有的。
原本以為zTree可以給我一個很好的封裝實現,結果懵逼都來不急。沒有這樣的實現,沒轍了改造,在jquery.zTree代碼中封裝了一個方法來實現這樣的移植功能。
代碼如下:
getStarNodes: function () { var tp = []; var list = []; //獲取當前樹選擇的數據結構 var treeData = data.getRoot(setting).children; //數據移植到新變量上操作 var par = $.extend(true, [], treeData); for (var i = 0; i < par.length; i++) { if (par[i].checked == true) { tp = []; for (var j = 0; j < par[i].children.length; j++) { if (par[i].children[j].checked == true) { tp.push(par[i].children[j]); } } par[i].children = tp; list.push(par[i]) } } return list; }
在上段代碼中:
變量tp是個臨時數組
變量list是裝最終的數據的數組
變量treeData是通過zTree中getRoo方式獲取數據
getRoot: function (setting) { return setting ? roots[setting.treeId] : null; }
在這里直接return roots[setting.treeId] 如果setting對象是false則返回null。zTree中初始就定義了roots={},用roots保存完整數據,
注意:當treeData獲取到數據是數組形式,不能直接for循環操作其數組,因為會在獲取數據中的children重新賦值,par[i].children = tp;如果拿原來數據結構的則造成數據混亂,必須復制一個獨立的數據進行操作,這樣才能把原數據和操作之后的數據隔離開,這里用jquery的extend方法來實現數據移植。
在樹對象新增操作的時候直接調用getStarNodes即可:
var tree1 = $.fn.zTree.getZTreeObj("tree"); var nodeList = tree1.getStarNodes();
將nodeList(通過getStarNodes方式過濾的數組)傳給新樹對象中去
var tree2 = $.fn.zTree.getZTreeObj("tree2"); tree2.addNodes(null, nodeList, null);
新樹對象tree2就可以拿這個數據結構遍歷了。這個功能就這樣實現了。在這個操作中,我們用到addNodes方法,但是我用的發現一個bug。在我每次點擊新增的時候就addNodes就會上次選擇的數據繼續累加在新的數據里面,我加了一個清空處理數據就不會出現重復累加。下面zTree源碼中操作
addNodes: function (setting, parentNode, index, newNodes, isSilent) { if (setting.data.keep.leaf && parentNode && !parentNode.isParent) { return; } if (!tools.isArray(newNodes)) { newNodes = [newNodes]; } if (setting.data.simpleData.enable) { newNodes = data.transformTozTreeFormat(setting, newNodes); } if (parentNode) { var target_switchObj = $$(parentNode, consts.id.SWITCH, setting), target_icoObj = $$(parentNode, consts.id.ICON, setting), target_ulObj = $$(parentNode, consts.id.UL, setting); if (!parentNode.open) { view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE); view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE); parentNode.open = false; target_ulObj.css({ "display": "none" }); } data.addNodesData(setting, parentNode, index, newNodes); view.createNodes(setting, parentNode.level + 1, newNodes, parentNode, index); if (!isSilent) { view.expandCollapseParentNode(setting, parentNode, true); } } else { //在這里對數據進行清空處理,這樣方式是處理方法其中之一 data.getRoot(setting).children = []; data.addNodesData(setting, data.getRoot(setting), index, newNodes); view.createNodes(setting, 0, newNodes, null, index); } }
這樣UI交互也實現了,也保證所選數據結構正確,才能正常使用。