一、引言
我今天做了一个Ztree树增删改查菜单的功能。其中遇到了很多坑爹的问题,和大家讲述一下。
二、代码展示
1、Ztree树前台代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <link rel="stylesheet" href="${pageContext.request.contextPath }/pub/js/zTree/css/zTreeStyle/demo.css" type="text/css"> <link rel="stylesheet" href="${pageContext.request.contextPath }/pub/js/zTree/css/zTreeStyle/zTreeStyle.css" type="text/css"> <script type="text/javascript" src="${pageContext.request.contextPath}/pub/js/zTree/js/jquery.ztree.core-3.5.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/pub/js/zTree/js/jquery.ztree.excheck-3.5.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/pub/js/zTree/js/jquery.ztree.exedit-3.5.js"></script> <script type="text/javascript"> var setting = { async : { enable : true,//开启异步加载处理 url : encodeURI(encodeURI("${pageContext.request.contextPath }/right/list.html")), autoParam : [ "id" ], dataFilter : filter, contentType : "application/json", type : "get" }, view : { expandSpeed : "", addHoverDom : addHoverDom, removeHoverDom : removeHoverDom, selectedMulti : false }, edit : { enable : true }, data : { simpleData : { enable : true } }, callback : { beforeRemove : beforeRemove, beforeRename : beforeRename, } }; function filter(treeId, parentNode, childNodes) { var nodes = JSON.parse(childNodes.data); if (!nodes) return null; for (var i = 0, l = nodes.length; i < l; i++) { nodes[i].name = nodes[i].name.replace(/.n/g, '.'); } return nodes; } function beforeRemove(treeId, treeNode) { if (confirm("确认删除节点--" + treeNode.name + "--吗?")) { var param = "id=" + treeNode.id; $.post(encodeURI(encodeURI("${pageContext.request.contextPath }/right/deleteRight.html?" + param))); } else { return false; } } function beforeRename(treeId, treeNode, newName) { if (newName.length == 0) { alert("节点名称不能为空."); return false; } var param = "id=" + treeNode.id + "&name=" + newName; $.post(encodeURI(encodeURI("${pageContext.request.contextPath }/right/editRight.html?" + param))); return true; } function addHoverDom(treeId, treeNode) { var sObj = $("#" + treeNode.tId + "_span"); if (treeNode.editNameFlag || $("#addBtn_" + treeNode.tId).length > 0) return; var addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='add node' onfocus='this.blur();'></span>"; sObj.after(addStr); var btn = $("#addBtn_" + treeNode.tId); if (btn) btn.bind("click", function() { var Ppname = prompt("请输入新节点名称"); if (Ppname == null) { return; } else if (Ppname == "") { alert("节点名称不能为空"); } else { var param ="&pId="+ treeNode.id + "&name=" + Ppname; var zTree = $.fn.zTree.getZTreeObj("treeDemo"); $.post( encodeURI(encodeURI("${pageContext.request.contextPath }/right/save.html?" + param)), function(data) { if ($.trim(data) != null) { var treenode = $.trim(data); zTree.addNodes(treeNode, { pId : treeNode.id, name : Ppname }, true); } }) } }); }; function removeHoverDom(treeId, treeNode) { $("#addBtn_" + treeNode.tId).unbind().remove(); }; $(document).ready(function() { $.fn.zTree.init($("#treeDemo"), setting); }); </script> <style type="text/css"> .ztree li span.button.add { margin-left: 2px; margin-right: -1px; background-position: -144px 0; vertical-align: top; *vertical-align: middle } </style> <div class="content_wrap"> <div class="zTreeDemoBackground left"> <ul id="treeDemo" class="ztree"></ul> </div> </div>
2、后台代码
package com.hzwealth.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.hzwealth.common.vo.SysConstant; import com.hzwealth.common.vo.SysResult; import com.hzwealth.pojo.Right; import com.hzwealth.pojo.User; import com.hzwealth.service.RightService; import com.hzwealth.service.RoleService; /** * 菜单管理 * @author lixiaochao *create Date : 2017/1/6 17:08 */ @Controller @RequestMapping("/right") public class RightController { @Autowired private RightService rightService; @Autowired private RoleService roleService; /** * 修改菜单 * @param right * @return */ @RequestMapping("/editRight") @ResponseBody public SysResult editRight(Right right){ rightService.editRight(right); return SysResult.ok(); } /** * 删除菜单 * @param rightId * @return */ @RequestMapping("/deleteRight") @ResponseBody public SysResult deleteRight(Long rightId){ rightService.deleteRight(rightId); return SysResult.ok(); } /** * 添加菜单 * @param right * @return */ @RequestMapping("/save") @ResponseBody public SysResult save(Right right){ rightService.addRight(right); return SysResult.ok(); } /** * 显示信息菜单 * @param session * @return */ @RequestMapping("/list") @ResponseBody public SysResult list(HttpServletRequest request){ if(request==null|| request.getSession().getAttribute(SysConstant.CURRENT_USER_INFO)==null){ return SysResult.build(300, "当前用户未登录,请重新登录"); } User user = (User)request.getSession().getAttribute(SysConstant.CURRENT_USER_INFO); String jsonStr = roleService.getRJsonStr(user.getRoleId()); //request.getSession().setAttribute("jsonStr", jsonStr); //System.out.println(request.getSession().getAttribute("jsonStr")); return SysResult.ok(jsonStr);//发送前台jsonStr json字符串 } }
其中roleService.getRJsonStr() 方法为:
/** * 展示菜单list 菜单管理模块 * @param roleId * @return */ public String getRJsonStr(Long roleId){ List<Right> rightList = rightMapper.select(null); JSONArray array = new JSONArray(); for(Right right :rightList){ JSONObject jsonObject = new JSONObject(); jsonObject.put("id", right.getId()); jsonObject.put("name", right.getRightName()); jsonObject.put("pId", right.getParentId()); array.put(jsonObject); } return array.toString(); }
三、阐述问题及解决方案
1、问题一:第一次加载的时候不会显示数据,刷页面,第二次点开页面才会加载出菜单。
解决方案:我后台用的是SysResult来返回结果,结果有返回信息,返回码和传到前台的数据。Ztree异步加载机制是先访问那个url,然后在进入后台,然后在返回数据进入 filter,进入filter处理数据。childNodes是SysResult,所以直接用它来显示,第一次根本显示不出来。所以我后来用var node = childNodes.data来接受数据。但是出现了问题二的问题。
2、问题二:cannot read property 'replace' of undefined,不识别relace,
解决方案:我通过使用debugger(google浏览器可用,火狐我用不了),来查到node[i].name是一个双引号,根本没有拿到name后来我才知道,我们需要用js的JSON.parse(childNodes.data)来转化。这是将json字符串转换为json对象。问题解决。
四、总结
1、首先遇到问题,我们不要害怕,相反我们应该庆幸,因为每次遇到问题我们都是成长的过程。
2、遇到问题,冷静思考,不要盲目的百度,google,学一样东西,首先先把它的API大致看一看,遇到问题深入学习它的API。
Ztree API文档,demo:http://download.csdn.net/download/xiaochaolovedan/9733857
3、遇到问题,最好的办法大家都知道,就是debug,非常的方便,通过debugger来研究问题,一目了然。
4、少用eval,eval不安全,下面是详细介绍:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval