JQuery zTree树特殊需求及解决方案
最近因公司使用到jquery ztree解决一个大数量的机构案例,做个记录供参考。
总需求:属于权限分配,以树形结构显示机构层级,勾选的机构表示拥有指定的权限,并能进行编辑。
技术需要:要求有联动选择与取消选择,如果子分部全部选择,只需要保存上级机构ID。
开始考虑到机构数比较多,有成千上万,而且后继还可能继续增加。所以初期用的是ajax形式多次加载树,但发现问题很多:
1、呈现效果不理想:假如起初在第三级下选择了一个机构,编辑时看到一级机构时全是没选择,也没有呈现半选择状态。直到ajax加载到第三级时,一级二级才突然出现半选状态。而且子节点子子节点无法出现选择效果,还没考虑以后再添加或者删除子节点情况。
2、编辑时丢失数据:假如开始选择了二级某个节点立刻保存,编辑时进入二级时再ajax第三级机构,二级机构就会因三级机构全部末选择而自动变成半选状态,又因半选状态机构是不会保存。
3、数据重叠:假如开始选择第三级某个节点,编辑时ajax到它的第二级父节点并选择,因无法判断它们是父子关系而保存了重叠节点。
4、取消操作无法还原数据:因为机构树是以弹窗选择的,弹出后可任意选择树,如果“确定”就显示对应选择的节点,如果“取消”后再弹出机构数无法取消这次选择的节点(这里操作全是前端操作,并没存入数据库,而树又是一次生成,又不可能从节点的点击事件去判断那些操作,太复杂了。)
……还有其他没考虑到的问题等,结果那一夜第一次加班直到晚上九点才回去
解决方案:一次加载所有机构数,查询过数据库所有机构暂时为四千左右,预计未来三年也不会超过万数。保存时不再从已经选择的节点中循环读取,而是从所有根节点中循环读子节点,直到判断本节点是全选状态。每次弹出树都先取消所有节点的选择。然后从已选值中判断哪些节点已经选择,然后循环所有子节点让其选择,并循环所有父节点让其呈现半选择状态。
<script type="text/javascript" src="../../js/jquery-1.4.4.min.js"></script> <script type="text/javascript" src="../../js/jquery.ztree.core-3.5.js"></script> <script type="text/javascript" src="../../js/jquery.ztree.excheck-3.5.js"></script> <link rel="stylesheet" href="../../css/zTreeStyle/zTreeStyle.css" type="text/css"/> <SCRIPT type="text/javascript" > var setting = { check: { enable: true, //可选择状态 chkboxType: { "Y" : "ps", "N" : "ps" }//选择取消时联动 }, data: { simpleData: { enable: true } } }; var treeObj,//树对象 tree_nodes,//所有树节点 rootNodesArray=[],//树根节点集合 getval={name:",",id:","};//已选择的节点名称与ID //打开树\确定\取消按钮函数 function funTree(t){ if(t=="open"){ if(!tree_nodes){ $.getJSON("json.asp",function(a){ $.fn.zTree.init($("#tree"), setting,a); treeObj = $.fn.zTree.getZTreeObj("tree"); //treeObj.expandAll(true);//打开所有节点 tree_nodes = treeObj.transformToArray(treeObj.getNodes());//获取所有节点 reset_tree(true); }); }else{ treeObj.checkAllNodes(false);//取消所有节点选择 reset_tree(false); } }else{ if(t=="ok"){ getval.id=getval.name="," for(var l=0;l<rootNodesArray.length;l++){ get_checkNodeValue(rootNodesArray[l]); console.log(rootNodesArray[l]); } $("#id").val(getval.id); $("#name").val(getval.name); } $("#tree_div").hide(); } } //重载树结构 function reset_tree(root){ for(var i=0;i<tree_nodes.length;i++){ var node=tree_nodes[i]; if(root&&node.parentTId==null){ rootNodesArray.push(node);//获取所有根节点 } if(getval.id.indexOf(","+node.id+",")!=-1){ node.checked=true; node.halfCheck=false; node.check_Child_State=2; treeObj.updateNode(node); tree_checkAndUpdate(node,"s");//循环勾选子节点并更新 tree_checkAndUpdate(node,"p");//循环半勾选父节点并更新 } } treeObj.refresh();//刷新整个树 $("#tree_div").show();//弹出树窗口 } //循环勾选节点并更新函数 function tree_checkAndUpdate(node,ps){ if(ps=="s"){ if(node.children){ var c=node.children; for(var n=0;n<c.length;n++){ c[n].checked=true; treeObj.updateNode(c[n]); tree_checkAndUpdate(c[n],ps); } } }else{ var p=node.getParentNode(); if(p){ p.checked=true; p.check_Child_State=1; treeObj.updateNode(p); tree_checkAndUpdate(p,ps); } } } //循环读取已经选择的节点值 function get_checkNodeValue(node){ if(!node){ return false;//不存在的节点 } if(node.check_Child_State==1){ var c=node.children;//如果部分子节点已选择就进入循环子节点 for(var i=0;i<c.length;i++){ get_checkNodeValue(c[i]); } }else if(node.checked){//本节点已经选择,赋值并终止循环 getval.id +=node.id+","; getval.name+=node.name+","; } } </SCRIPT> <div> <p>选择树的名称:<input type="text" id="name" name="name" style="width:400px" /></p> <p>选择树的I D:<input type="text" id="id" name="id" style="width:400px" /></p> <button type="button" onclick="funTree('open')">打开树</button> </div> <div id="tree_div" style="display:none;border:1px solid #ddd;width:300px;"> <ul id="tree" class="ztree" style="width:300px; overflow:auto;"></ul> <button type="button" onclick="funTree('ok')">确定</button> <button type="button" onclick="funTree('colse')">关闭</button> </div>
演示效果:点击这里浏览
关键词: jquery,ztree,树形菜单 编辑时间: 2013-09-15 13:30:37
0
高兴1
支持0
搞笑0
不解0
谎言1
枪稿0
震惊0
无奈0
无聊0
反对0
愤怒
- 暂无评论
网友评论