
说明:前端初始化数据,且数据采用标准json数据格式,构建最简单的树。 注意:ZTree依赖于jquery实现,所以要先加载css -》jquery -》ztree.js

案例原型对应官网下面的demo

<head>
<!--先加载css,再加载js,否则可能出错-->
<link th:href="@{bootstrap-3.4.1-dist/css/bootstrap.css}" rel="stylesheet" />
<link th:href="@{bootstrap-3.4.1-dist/css/bootstrap-theme.css}" rel="stylesheet" />
<!--<link th:href="@{zTree_v3-master/css/metroStyle/metroStyle.css}" rel="stylesheet" type="text/css" />-->
<link th:href="@{zTree_v3-master/css/zTreeStyle/zTreeStyle.css}" rel="stylesheet" type="text/css" />
<link th:href="@{zTree_v3-master/css/demo.css}" rel="stylesheet" type="text/css" />
<!--切记:先加载jquery的js,再加载bootstrap.js-->
<script th:src="@{jquery/jquery3.6.0.js}"></script>
<script th:src="@{bootstrap-3.4.1-dist/js/bootstrap.js}"></script>
<script type="text/javascript" th:src="@{zTree_v3-master/js/jquery.ztree.all.js}" ></script>
</head> <!--需求1:前端初始化数据(标准json数据)-->
<div class="col-md-7">
<hr><p>需求1:前端初始化数据(标准json数据)</p>
<ul id="treeDemo" class="ztree"></ul>
</div>//需求1配置:前端初始化数据(标准json数据)
var setting0 = {
data: {
simpleData: {
enable: true, //true 、 false 分别表示 使用 、 不使用 简单数据模式
idKey: "id", //节点数据中保存唯一标识的属性名称
pIdKey: "parentId", //节点数据中保存其父节点唯一标识的属性名称
rootPId: -1 //用于修正根节点父节点数据,即 pIdKey 指定的属性值
},
key: {
name: "name" //zTree 节点数据保存节点名称的属性名称 默认值:"name"
}
}
};
//需求1:前端初始化数据
var zNodes = [
//注意,数据中的 menuName 必须与 settingss 中key 中定义的name一致,否则找不到
{name:"父节点1", open:true, children:[
{name:"子节点1"}, {name:"子节点2"}]},
{name:"父节点2", open:true, children:[
{name:"子节点3"}, {name:"子节点4"}]}
];
zTreeObj = $.fn.zTree.init($("#treeDemo"), setting0, zNodes); //初始化树
zTreeObj.expandAll(true); //true 节点全部展开、false节点收缩该案例要实现4个功能: 1)后端查询ztree数据
2)设置节点默认选中 3)【添加/编辑/删除】节点 4)自定义图标固定和不固定显示 为了方便这4个功能写到一个案例中
碰到的问题1:增加按钮一直显示空心正方形,而没有小+号图标, 解决方案: 第一种:css样式由zTreeStyle.css -》 调整为metroStyle.css,也就是使用黑白主题的样式,就会显示添加图标 第二种:使用zTreeStyle.css样式的时候,style标签追加图标地址,也就是下面的

碰到的问题2:自定义添加按钮一直无限的增加显示出来
解决方案:js中使用下面的校验,详情请看方法 function addDiyDom()
if (treeNode.editNameFlag || $("#" + treeNode.tId + "_add").length>0) return; //注意:该条件保证添加图标不会一直重复添加

案例原型对应官网下面的demo


<!--需求4和需求5配置:必须设置图标url,否则图标不显示,只显示个空白正方形-->
<style type="text/css">
.ztree li span.button.icon01{margin:0; background: url(zTree_v3-master/css/zTreeStyle/img/diy/1_close.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
.ztree li span.button.icon02{margin:0; background: url(zTree_v3-master/css/zTreeStyle/img/diy/5.png) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
</style><!--需求2:后端查询ztree数据(简单JSON数据)-->
<div class="col-md-7">
<hr><p>需求2:后端查询ztree数据(简单JSON数据)</p>
<ul id="ajaxQueryTree" class="ztree"></ul>
</div>//需求2配置:后端查询ztree数据(简单JSON数据)
var setting1 = {
data: {
simpleData: {
enable: true, //true 、 false 分别表示 使用 、 不使用 简单数据模式
idKey: "id", //节点数据中保存唯一标识的属性名称
pIdKey: "parentId", //节点数据中保存其父节点唯一标识的属性名称
rootPId: -1 //用于修正根节点父节点数据,即 pIdKey 指定的属性值
},
key: {
name: "name" //zTree 节点数据保存节点名称的属性名称 默认值:"name"
}
},
check:{
enable:true, //true 、 false 分别表示 显示 、不显示 复选框或单选框
nocheckInherit:true //当父节点设置 nocheck = true 时,设置子节点是否自动继承 nocheck = true
},
edit: {
enable: true
},
callback: {
beforeRemove: zTreeBeforeRemove, //用于捕获节点被删除之前的事件回调函数,并且根据返回值确定是否允许删除操作
onRemove: zTreeOnRemove, //用于捕获删除节点之后的事件回调函数
beforeRename: zTreeBeforeRename, //用于捕获节点编辑名称结束(Input 失去焦点 或 按下 Enter 键)之后,更新节点名称数据之前的事件回调函数,并且根据返回值确定是否允许更改名称的操作
onRename: zTreeOnRename //用于捕获节点编辑名称结束之后的事件回调函数
},
view : {
addDiyDom: addDiyDom, //用于在节点上固定显示用户自定义控件
selectedMulti: false, //设置是否允许同时选中多个节点
showLine : true, //设置 zTree 是否显示节点之间的连线
addHoverDom: addHoverDom, //用于当鼠标移动到节点上时,显示用户自定义控件
removeHoverDom: removeHoverDom, //用于当鼠标移出节点时,隐藏用户自定义控件
}
};
//需求2:后端查询ztree数据
$(document).ready(function(){
$.ajax({
type:"get",
url:"http://localhost:8888/getEquipmentList",
async:true,
success:function(res){
zTreeObj = $.fn.zTree.init($("#ajaxQueryTree"), setting1, res.info); //初始化树
zTreeObj.expandAll(true); //true 节点全部展开、false节点收缩
//需求3:设置节点默认选中
var node = zTreeObj.getNodeByParam("id", 0);
zTreeObj.checkNode(node, true, false, false);
}
});
});
//需求4:【添加/编辑/删除】节点
var newCount = 100;
function addHoverDom(treeId, treeNode) {
var sObj = $("#" + treeNode.tId + "_span");
if (treeNode.editNameFlag || $("#" + treeNode.tId + "_add").length>0) return; //注意:该条件保证添加图标不会一直重复添加
var addStr = "<span class='button icon01' id='" + treeNode.tId + "_add' title='add'></span>";
sObj.after(addStr);
var btn = $("#"+treeNode.tId + "_add");
if (btn) btn.bind("click", function(){
var zTree = $.fn.zTree.getZTreeObj("ajaxQueryTree");
zTree.addNodes(treeNode, {id:newCount, pId:treeNode.id, name:"add_" + (newCount++)});
return false;
});
}
function removeHoverDom(treeId, treeNode) {
$("#" + treeNode.tId + "_add").unbind().remove();
}
function zTreeBeforeRemove(treeId, treeNode) {
alert("删除节点前{:" + "id=" + treeNode.id + ", " + "parentId=" + treeNode.parentId + ", " + "name=" + treeNode.name + ", " + "level=" + treeNode.level +", "+ "tId=" + treeNode.tId + "}");
}
function zTreeOnRemove(event, treeId, treeNode) {
alert("删除节点后{:" + "id=" + treeNode.id + ", " + "parentId=" + treeNode.parentId + ", " + "name=" + treeNode.name + ", " + "level=" + treeNode.level +", "+ "tId=" + treeNode.tId + "}");
}
function zTreeBeforeRename(treeId, treeNode, newName, isCancel) {
alert("编辑节点前{:" + "id=" + treeNode.id + ", " + "parentId=" + treeNode.parentId + ", " + "name=" + treeNode.name + ", " + "level=" + treeNode.level +", "+ "tId=" + treeNode.tId + "}");
}
function zTreeOnRename(event, treeId, treeNode, isCancel) {
alert("编辑节点后{:" + "id=" + treeNode.id + ", " + "parentId=" + treeNode.parentId + ", " + "name=" + treeNode.name + ", " + "level=" + treeNode.level +", "+ "tId=" + treeNode.tId + "}");
}
//需求5:自定义图标固定和不固定显示
function addDiyDom(treeId, treeNode) {
if (treeNode.id == 3) {
var sObj = $("#" + treeNode.tId + "_span");
if (treeNode.editNameFlag || $("#" + treeNode.tId + "_add").length>0) return; //注意:该条件保证添加图标不会一直重复添加
var addStr = "<span class='button icon02' id='" + treeNode.tId + "_add' title='add'></span>";
sObj.after(addStr);
var btn = $("#"+treeNode.tId + "_add");
if (btn) btn.bind("click", function(){
var zTree = $.fn.zTree.getZTreeObj("ajaxQueryTree");
zTree.addNodes(treeNode, {id:newCount, pId:treeNode.id, name:"add_" + (newCount++)});
return false;
});
}
}Equipment实体
package com.example.demo.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 装备
* @Author 211145187
* @Date 2022/3/26 10:15
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Equipment {
//id
private int id;
//父id
private int parentId;
//名称
private String name;
}Controller代码
//ZTree数据缓存
private ConcurrentHashMap<String, List<Equipment>> zTreeCache = new ConcurrentHashMap<>();
----------------------------------------------------------------------------------------------
@PostConstruct
public void initCacheEquipmentList() {
List<Equipment> equipmentList = new ArrayList<>();
equipmentList.add(new Equipment(0, -1, "装备"));
equipmentList.add(new Equipment(1, 0, "陆"));
equipmentList.add(new Equipment(2, 0, "海"));
equipmentList.add(new Equipment(3, 0, "空"));
equipmentList.add(new Equipment(4, 1, "东风2号"));
equipmentList.add(new Equipment(5, 1, "坦克"));
equipmentList.add(new Equipment(6, 2, "潜艇"));
equipmentList.add(new Equipment(7, 2, "巡洋舰"));
equipmentList.add(new Equipment(8, 3, "隐形飞机"));
zTreeCache.put("equipmentList", equipmentList);
}
----------------------------------------------------------------------------------------------
//查询ZTree
@GetMapping(value = "/getEquipmentList")
@ResponseBody
public Response<List<Equipment>> getEquipmentList(Model model) {
List<Equipment> equipmentList = zTreeCache.get("equipmentList");
model.addAttribute("equipmentList", equipmentList);
equipmentList.stream().forEach(System.out::println);
return Response.success(equipmentList);
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。