一、引言

    我今天做了一个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

Ztree树增删改查菜单,遇到的问题总结的更多相关文章

  1. ztree使用系列三(ztree与springmvc+spring+mybatis整合实现增删改查)

    在springmvc+spring+mybatis里整合ztree实现增删改查,上一篇已经写了demo,以下就仅仅贴出各层实现功能的代码: Jsp页面实现功能的js代码例如以下: <script ...

  2. 可编辑树Ztree的使用(包括对后台数据库的增删改查)

    找了很多网上关于Ztree的例子和代码才搞定. 首先,关于Ztree的代码不介绍了,网上下载之后,引用下列四个文件就能使用了. 1.关于配置选项.主要通过回调函数来实现向后台发送数据,实现增删改查. ...

  3. [译]聊聊C#中的泛型的使用(新手勿入) Seaching TreeVIew WPF 可编辑树Ztree的使用(包括对后台数据库的增删改查) 字段和属性的区别 C# 遍历Dictionary并修改其中的Value 学习笔记——异步 程序员常说的「哈希表」是个什么鬼?

    [译]聊聊C#中的泛型的使用(新手勿入)   写在前面 今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发 ...

  4. .NET ORM框架HiSql实战-第二章-使用Hisql实现菜单管理(增删改查)

    一.引言 上一篇.NET ORM框架HiSql实战-第一章-集成HiSql 已经完成了Hisql的引入,本节就把 项目中的菜单管理改成hisql的方式实现. 菜单管理界面如图: 二.修改增删改查相关代 ...

  5. JavaScript---Dom树详解,节点查找方式(直接(id,class,tag),间接(父子,兄弟)),节点操作(增删改查,赋值节点,替换节点,),节点属性操作(增删改查),节点文本的操作(增删改查),事件

    JavaScript---Dom树详解,节点查找方式(直接(id,class,tag),间接(父子,兄弟)),节点操作(增删改查,赋值节点,替换节点,),节点属性操作(增删改查),节点文本的操作(增删 ...

  6. 【硬核】使用替罪羊树实现KD-Tree的增删改查

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习的第16篇文章,我们来继续上周KD-Tree的话题. 如果有没有看过上篇文章或者是最新关注的小伙伴,可以点击一下下方的传送门: ...

  7. EasyUI + Spring MVC + hibernate实现增删改查导入导出

    (这是一个故事--) 前言 作为一个JAVA开发工程师,我觉得最基本是需要懂前端.后台以及数据库. 练习的内容很基础,包括:基本增删改查.模糊查询.分页查询.树菜单.上传下载.tab页 主管发我一个已 ...

  8. MVC无限级分类02,增删改查

    继上一篇"MVC无限级分类01,分层架构,引入缓存,完成领域模型与视图模型的映射",本篇开始MVC无限级分类的增删改查部分,源码在github. 显示和查询 使用datagrid显 ...

  9. 【ztree】zTree节点增删改

    今天遇到一个需求是对zTree的节点进行增删改,经过查阅资料总结如下: 效果: 完成增删改,要注意几个关键点: 使用 编辑功能,必须设置 setting.edit 中的各个属性 使用 编辑功能的事件回 ...

随机推荐

  1. JavaScript中instanceof的判断依据

    读jquery源码的时候,发现作者为了让创建jquery对象更容易使用了用函数返回对象的方法 jQuery = function( selector, context ) { return new j ...

  2. Linux wget 批量下载

    需求:已知50个pdf的URL地址,需要批量下载,该怎么办呢? 方案一:使用wget自带的一个功能 -i 选项  从指定文件中读取下载地址,这样的好处是一直是这一个wget进程下载所有pdf,不会来回 ...

  3. 【模板】prufer序列

    如何构造一个prufer序列? 我们给一棵无根树的节点编上号,每次找到一个编号最小的度为1节点,删除它,并输出与它连接的点的编号,直到只剩下两个节点. 这样,我们就构造出来了一个prufer序列. 通 ...

  4. Redis持久化--Redis宕机或者出现意外删库导致数据丢失--解决方案

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! Red ...

  5. 6.1Hadoop属性Configuration配置API

    6.1  Hadoop属性配置API Hadoop需要添加一些自定义的属性值,可以通过Configuration类的实例来加载xml配置文件中的属性值. (1)   xml配置文件的格式 <?x ...

  6. 学习笔记之vim的使用

    很多刚学习linux编程的人总是对vim有一种恐惧,我自己就是这么回事的. 可是当你努力的去尝试学习使用后,才发现它的精髓所在. 在我看来,让vim变得好用的前提是要安装两个插件,ctags和tagl ...

  7. 009-2010网络最热的 嵌入式学习|ARM|Linux|wince|ucos|经典资料与实例分析

    前段时间做了一个关于ARM9 2440资料的汇总帖,很高兴看到21ic和CSDN等论坛朋友们的支持和鼓励.当年学单片机的时候datasheet和学习资料基本都是在论坛上找到的,也遇到很多好心的高手朋友 ...

  8. Linux下mysql 多实例安装配置

    首先我们要清楚什么是多实例?所谓多实例就是用多个配置文件来启动多个不同端口的进程,以不同的端口的形式为外提供服务.明白了多实例 我们下面的操作和配置就一目了然了首先我们要安装一套基础的应用程序,也就是 ...

  9. 关于设备与canvas画不出来的解决办法

    连续四天解决一个在三星手机上面画canvas的倒计时饼图不出来的问题,困惑了很久,用了很多办法,甚至重写了那个方法,还是没有解决,大神给的思路是给父级加 "overflow: visible ...

  10. html部分知识点(待完善)

    html部分知识点 跳转 在A页面某链接处`<a href="#aa" target="_blank"></a> 在B页面指定的标题处定 ...