一、引言

    我今天做了一个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. WebSocket原理及技术简介

    摘要: WebSocket用于在Web浏览器和服务器之间进行任意的双向数据传输的一种技术.WebSocket协议基于TCP协议实现,包含初始的握手过程,以及后续的多次数据帧双向传输过程.其目的是在We ...

  2. 【Linux系列】Linux基础知识整理

    Linux操作系统在服务器领域广泛的使用到,作为一个后台开发工程师很有必要了解Linux相关的知识. 本篇日志是我学习Linux过程中的简单记录和总结.本着"理论够用,实践为主"的 ...

  3. 【Leetcode 做题学算法周刊】第二期

    首发于微信公众号<前端成长记>,写于 2019.11.05 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 20 ...

  4. Go语言入门:Hello world

    本文是「vangoleo的Go语言学习笔记」系列文章之一. 官网: http://www.vangoleo.com/go/go-hello-world/ 在上一篇文章你好,Go语言中,我们对Go语言的 ...

  5. Java 用单向循环链表实现 约瑟夫问题

    public class lianbiao2 { class Node{ Node next; int number; public Node getNext() { return next; } p ...

  6. Azure 上的物联网产品介绍

    微软云Azure上物联网产品提供了从设备接入到设备与云的双向通信,到数据在云中存储,到数据分析,最后到数据展示的完整解决方案,本文主要介绍一些基本的概念,后续的章节中,会详细介绍每款产品的使用方法及步 ...

  7. Mybatis:CRUD操作

    提示: Mapper配置文件的命名空间为对应接口包名+接口名字,这个经常会忘记和搞错的!! select标签 在接口中编写三个查询方法 //获取全部用户List<User> selectU ...

  8. Ubuntu18.04系统下安装Pycharm&vim设置自动缩进及默认显示行号

    Ubuntu18.04系统自带python3.6及python2.7,Pycharm是一款非常强大的IDE.目前Pycharm有两个版本:专业版和Community社区,区别是专业版是收费,而且功能更 ...

  9. [考试反思]1008csp-s模拟测试65:突袭

    博客园挂了,不让粘图. 写的朴素一点. #1:100+100+25=225 #2:100+70+35=205 #2:100+60+45=205(我) 回到第一机房还算不错的第一仗. 考完之后我以为我A ...

  10. [考试反思]阶段性总结:NOIP模拟测试7~13

    苟且Rank#1.第二次分机房结束. 得到了喘息一会的权利. 在最后两场考试中大脸skyh慷慨舍弃264分让出Rank#1的故事也十分感人 然而还是有很多东西值得思考. 虽说是反思,但是还是有一些地方 ...