ZTree基本使用及本人详解

article/2025/9/14 4:10:52

文章目录

  • ZTree树简介
    • 简介
    • ZTree的特点
    • 练习ztree之前的小建议
    • ZTree文件介绍
    • ZTree的配置介绍
  • ZTree使用案例
    • 需求1:前端初始化数据(标准json数据)
      • 前端代码
    • 需求2:后端查询ztree数据(简单JSON数据)+需求3:设置节点默认选中+需求4:【添加/编辑/删除】节点+需求5:自定义图标固定和不固定显示
      • 前端代码
      • 后端代码
    • 需求6:左侧菜单栏
      • 前端代码
    • 需求7:拖拽节点高级控制
      • 前端代吗
    • 需求8:2棵树之间的数据交互
      • 前端代吗

ZTree树简介

简介

在这里插入图片描述

ZTree的特点

在这里插入图片描述

练习ztree之前的小建议

如果一上来看官网估计找不准哪个是配置,哪个是事件回调函数…,可以把源码下载本地,然后进入
D:\zTree_v3-master\demo\cn文件下点开index.heml里面有所有的案例,这时候精确找到自己要练习的案例网页代码,然后F12进行删减,把多余的css+js+文字说明,都删掉这样方便整体练习及了解。

在这里插入图片描述
在这里插入图片描述

ZTree文件介绍

在这里插入图片描述

ZTree的配置介绍

在这里插入图片描述

ZTree使用案例

需求1:前端初始化数据(标准json数据)

说明:前端初始化数据,且数据采用标准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节点收缩

需求2:后端查询ztree数据(简单JSON数据)+需求3:设置节点默认选中+需求4:【添加/编辑/删除】节点+需求5:自定义图标固定和不固定显示

该案例要实现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 {//idprivate int id;//父idprivate 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);
}

需求6:左侧菜单栏

注意点1: 初始化组件加载方法 $(document).ready(function(){})不知道内部干了啥,我添加了注释,方便对照理解
注意点2:方法beforeClick()里面执行流程很绕,所以我梳理了下在方法上加入了执行流程说明,方便对照理解

碰到的问题:因为我所有案例写在同一个页面,加入菜单案例后把别的案例的样式都给改变了
解决方案:设置css样式时先进行id过滤 ,详情看下面的
在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

前端代码

<!--需求6:左侧菜单栏   注意:按id进行筛选,否则会干扰其他树结构样式-->
<style type="text/css">#leftMenuTree li a.level0 {width:200px;height: 20px; text-align: center; display:block; background-color: #0B61A4; border:1px silver solid;}#leftMenuTree li a.level0.cur {background-color: #66A3D2; }#leftMenuTree li a.level0 span {display: block; color: white; padding-top:3px; font-size:12px; font-weight: bold;word-spacing: 2px;}#leftMenuTree li a.level0 span.button {	float:right; margin-left: 10px; visibility: visible;display:none;}#leftMenuTree li span.button.switch.level0 {display:none;}</style>
<!--需求6:左侧菜单栏-->
<!--左侧菜单栏 注意:ul的class必须为ztree否则样式没效果,同时div的class指定为zTreeDemoBackground left-->
<div class="col-md-7"><hr><p>需求6:左侧菜单栏</p><ul id="leftMenuTree" class="ztree"></ul>
</div>
//需求6配置:左侧菜单栏var setting6 = {data: {simpleData: {enable: true,  //true 、 false 分别表示 使用 、 不使用 简单数据模式}},callback: {onNodeCreated: this.onNodeCreated,  //用于捕获节点生成 DOM 后的事件回调函数beforeClick: this.beforeClick,      //用于捕获单击节点之前的事件回调函数,并且根据返回值确定是否允许单击操作onClick: this.onClick               //用于捕获节点被点击的事件回调函数},view : {selectedMulti: false,                //设置是否允许同时选中多个节点showLine : true,                    //设置 zTree 是否显示节点之间的连线dblClickExpand: false               //双击节点时,是否自动展开父节点的标识}};var curMenu = null, zTree_Menu = null;var zNodes6 =[{ id:1, pId:0, name:"主菜单 1", open:true},        //open:true,记录 treeNode 节点的 展开 / 折叠 状态{ id:11, pId:1, name:"子菜单 1-1"},{ id:111, pId:11, name:"叶子节点 1-1-1"},{ id:112, pId:11, name:"叶子节点 1-1-2"},{ id:113, pId:11, name:"叶子节点 1-1-3"},{ id:114, pId:11, name:"叶子节点 1-1-4"},{ id:12, pId:1, name:"子菜单 1-2"},{ id:121, pId:12, name:"叶子节点 1-2-1"},{ id:122, pId:12, name:"叶子节点 1-2-2"},{ id:123, pId:12, name:"叶子节点 1-2-3"},{ id:124, pId:12, name:"叶子节点 1-2-4"},{ id:2, pId:0, name:"主菜单 2"},{ id:21, pId:2, name:"子菜单 2-1"},{ id:211, pId:21, name:"叶子节点 2-1-1"},{ id:212, pId:21, name:"叶子节点 2-1-2"},{ id:213, pId:21, name:"叶子节点 2-1-3"},{ id:214, pId:21, name:"叶子节点 2-1-4"},{ id:22, pId:2, name:"子菜单 2-2"},{ id:221, pId:22, name:"叶子节点 2-2-1"},{ id:222, pId:22, name:"叶子节点 2-2-2"},{ id:223, pId:22, name:"叶子节点 2-2-3"},{ id:224, pId:22, name:"叶子节点 2-2-4"}];$(document).ready(function(){$.fn.zTree.init($("#leftMenuTree"), setting6, zNodes6); //初始化树zTree_Menu = $.fn.zTree.getZTreeObj("leftMenuTree");curMenu = zTree_Menu.getNodes()[0].children[0].children[0]; //curMenu {id: 111, pId: 11, name: '叶子节点 1-1-1', level: 2, tId: 'leftMenuTree_3,....zTree_Menu.selectNode(curMenu);     //选中指定节点var a = $("#" + zTree_Menu.getNodes()[0].tId + "_a");       //获取id=“treeDemo_1_a” title="主菜单 1"的标签对象a.addClass("cur");  //添加css});function onClick(event, treeId, node) {alert("Do what you want to do!");}/*** 判断是否为父节点*      true:判断节点level === 0*          true:将第一个子节点“叶子结点1-1-1”赋值给pNode -》 按条件(pNode && pNode.level !==0)循环获取它的根节点“主菜单1”赋值给pNode -》 按条件(pNode !== node)判断当点击主菜单2时移除class(”cur“)等相关操作 -》判断children的open状态,进行相应的展开*          false:展开/折叠 指定的节点*      false:返回* @param treeId* @param node* @returns {boolean}*/function beforeClick(treeId, node) {    //treeId:leftMenuTree   node为每次点击的对象 node {id: 2, pId: null, name: '主菜单 2',...if (node.isParent) {if (node.level === 0) {var pNode = curMenu;while (pNode && pNode.level !==0) {pNode = pNode.getParentNode();  //获取到根节点}if (pNode !== node) {var a = $("#" + pNode.tId + "_a");a.removeClass("cur");zTree_Menu.expandNode(pNode, false);}a = $("#" + node.tId + "_a");a.addClass("cur");var isOpen = false;for (var i=0,l=node.children.length; i<l; i++) {if(node.children[i].open) {     //判断节点children的open状态isOpen = true;break;}}if (isOpen) {zTree_Menu.expandNode(node, true);curMenu = node;} else {zTree_Menu.expandNode(node.children[0].isParent?node.children[0]:node, true);curMenu = node.children[0];}} else {zTree_Menu.expandNode(node);    //展开 / 折叠 指定的节点}}return !node.isParent;}

需求7:拖拽节点高级控制

注意说明1:zNodes7配置中:
open:true,记录 treeNode节点的【展开/折叠】状态
drag:false,禁止拖拽
childOuter:false,禁止子节点移走
dropRoot该属性未知,我查不到
dropInner:false:不变为文件夹
注意说明2:方法dropPrev()+dropInner()+dropNext()就是用来判断【true/false】的

碰到的问题1: 为啥有的移动完目标节点变为文件夹,而“禁止子节点移走 2”下的移动完双方都还是文件,而没有目标节点变为文件夹
解决方案:setting -》edit -》drag -》 inner属性,inner属性用来控制移动后目标节点是否变为文件夹【true:目标节点变为文件夹/false:不变为文件夹】

在这里插入图片描述

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

在这里插入图片描述

前端代吗

<!--需求7:拖拽节点高级控制-->
<div class="col-md-7"><hr><p>需求7:拖拽节点高级控制</p><ul id="moveTree" class="ztree"></ul></div>
//需求7:拖拽节点高级控制var setting7 = {edit: {drag: {autoExpandTrigger: true,    //拖拽时父节点自动展开是否触发 onExpand 事件回调函数prev: dropPrev,     //拖拽到目标节点时,设置是否允许移动到目标节点前面的操作inner: dropInner,   //拖拽到目标节点时,设置是否允许成为目标节点的子节点    注意:inner属性用来控制移动后目标节点是否变为文件夹【true:目标节点变为文件夹/false:不变为文件夹】next: dropNext      //拖拽到目标节点时,设置是否允许移动到目标节点后面的操作},enable: true,           //设置 zTree 是否处于编辑状态showRemoveBtn: false,   //设置是否显示删除按钮showRenameBtn: false    //设置是否显示编辑名称按钮},data: {simpleData: {enable: true    //true 、 false 分别表示 使用 、 不使用 简单数据模式}},callback: {beforeDrag: beforeDrag,         //用于捕获节点被拖拽之前的事件回调函数,并且根据返回值确定是否允许开启拖拽操作beforeDrop: beforeDrop,         //用于捕获节点拖拽操作结束之前的事件回调函数,并且根据返回值确定是否允许此拖拽操作beforeDragOpen: beforeDragOpen, //用于捕获拖拽节点移动到折叠状态的父节点后,即将自动展开该父节点之前的事件回调函数,并且根据返回值确定是否允许自动展开操作onDrag: onDrag,                 //用于捕获节点被拖拽的事件回调函数onDrop: onDrop,                 //用于捕获节点拖拽操作结束的事件回调函数onExpand: onExpand              //用于捕获节点被展开的事件回调函数}};var zNodes7 =[{ id:1, pId:0, name:"随意拖拽 1", open:true},   //open:true,记录 treeNode节点的【展开/折叠】状态{ id:11, pId:1, name:"随意拖拽 1-1"},{ id:12, pId:1, name:"随意拖拽 1-2", open:true},{ id:121, pId:12, name:"随意拖拽 1-2-1"},{ id:122, pId:12, name:"随意拖拽 1-2-2"},{ id:123, pId:12, name:"随意拖拽 1-2-3"},{ id:13, pId:1, name:"禁止拖拽 1-3", drag:false},    //drag:false,禁止拖拽{ id:131, pId:13, name:"禁止拖拽 1-3-1", drag:false},{ id:132, pId:13, name:"禁止拖拽 1-3-2", drag:false},{ id:132, pId:13, name:"禁止拖拽 1-3-3", drag:false},{ id:2, pId:0, name:"禁止子节点移走 2", open:true, childOuter:false},  //childOuter:false,禁止子节点移走{ id:21, pId:2, name:"我不想成为父节点 2-1", dropInner:false},{ id:22, pId:2, name:"我不要成为根节点 2-2", dropRoot:false},   //dropRoot该属性未知,我查不到{ id:23, pId:2, name:"拖拽试试看 2-3"},{ id:3, pId:0, name:"禁止子节点排序/增加 3", open:true, childOrder:false, dropInner:false},  //dropInner:false:不变为文件夹{ id:31, pId:3, name:"随意拖拽 3-1"},{ id:32, pId:3, name:"随意拖拽 3-2"},{ id:33, pId:3, name:"随意拖拽 3-3"}];function dropPrev(treeId, nodes, targetNode) {var pNode = targetNode.getParentNode();if (pNode && pNode.dropInner === false) {return false;} else {for (var i=0,l=curDragNodes.length; i<l; i++) {var curPNode = curDragNodes[i].getParentNode();if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {return false;}}}return true;}function dropInner(treeId, nodes, targetNode) {if (targetNode && targetNode.dropInner === false) {return false;} else {for (var i=0,l=curDragNodes.length; i<l; i++) {if (!targetNode && curDragNodes[i].dropRoot === false) {return false;} else if (curDragNodes[i].parentTId && curDragNodes[i].getParentNode() !== targetNode && curDragNodes[i].getParentNode().childOuter === false) {return false;}}}return true;}function dropNext(treeId, nodes, targetNode) {var pNode = targetNode.getParentNode();if (pNode && pNode.dropInner === false) {return false;} else {for (var i=0,l=curDragNodes.length; i<l; i++) {var curPNode = curDragNodes[i].getParentNode();if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {return false;}}}return true;}var log, className = "dark", curDragNodes, autoExpandNode;function beforeDrag(treeId, treeNodes) {className = (className === "dark" ? "":"dark");for (var i=0,l=treeNodes.length; i<l; i++) {if (treeNodes[i].drag === false) {curDragNodes = null;return false;} else if (treeNodes[i].parentTId && treeNodes[i].getParentNode().childDrag === false) {curDragNodes = null;return false;}}curDragNodes = treeNodes;return true;}function beforeDragOpen(treeId, treeNode) {autoExpandNode = treeNode;return true;}function beforeDrop(treeId, treeNodes, targetNode, moveType, isCopy) {className = (className === "dark" ? "":"dark");return true;}function onDrag(event, treeId, treeNodes) {className = (className === "dark" ? "":"dark");}function onDrop(event, treeId, treeNodes, targetNode, moveType, isCopy) {className = (className === "dark" ? "":"dark");}function onExpand(event, treeId, treeNode) {if (treeNode === autoExpandNode) {className = (className === "dark" ? "":"dark");}}$(document).ready(function(){$.fn.zTree.init($("#moveTree"), setting7, zNodes7);});

需求8:2棵树之间的数据交互

注意说明:该案例需单独引入demo.css,同时div中的class名字好像必须指定官网给定的那个名字,比如class=“content_wrap”,class=“zTreeDemoBackground left”,class=“zTreeDemoBackground right”,
否则外面没有边框背景样式。

在这里插入图片描述

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

在这里插入图片描述

前端代吗

<!--需求82棵树之间的数据交互-->
<div class="content_wrap"><div class="zTreeDemoBackground left"><hr><p>需求82棵树之间的数据交互</p><ul id="leftMoveTree" class="ztree"></ul></div><div class="zTreeDemoBackground right"><ul id="rightMoveTree" class="ztree"></ul></div>
</div>
//需求8:2棵树之间的数据交互var setting8 = {edit: {enable: true,           //设置 zTree 是否处于编辑状态showRemoveBtn: false,   //设置是否显示删除按钮showRenameBtn: false    //设置是否显示编辑名称按钮},data: {simpleData: {enable: true    //true 、 false 分别表示 使用 、 不使用 简单数据模式}},callback: {beforeDrag: beforeDrag8,    //用于捕获节点被拖拽之前的事件回调函数,并且根据返回值确定是否允许开启拖拽操作beforeDrop: beforeDrop8     //用于捕获节点拖拽操作结束之前的事件回调函数,并且根据返回值确定是否允许此拖拽操作}};var zNodes8 =[{ id:1, pId:0, name:"父节点 1", open:true},{ id:11, pId:1, name:"叶子节点 1-1"},{ id:12, pId:1, name:"叶子节点 1-2"},{ id:13, pId:1, name:"叶子节点 1-3"},{ id:2, pId:0, name:"父节点 2", open:true},{ id:21, pId:2, name:"叶子节点 2-1"},{ id:22, pId:2, name:"叶子节点 2-2"},{ id:23, pId:2, name:"叶子节点 2-3"},{ id:3, pId:0, name:"父节点 3", open:true},{ id:31, pId:3, name:"叶子节点 3-1"},{ id:32, pId:3, name:"叶子节点 3-2"},{ id:33, pId:3, name:"叶子节点 3-3"}];function beforeDrag8(treeId, treeNodes) {for (var i=0,l=treeNodes.length; i<l; i++) {if (treeNodes[i].drag === false) {return false;}}return true;}function beforeDrop8(treeId, treeNodes, targetNode, moveType) {return targetNode ? targetNode.drop !== false : true;}$(document).ready(function(){$.fn.zTree.init($("#leftMoveTree"), setting8, zNodes8);$.fn.zTree.init($("#rightMoveTree"), setting8);});

http://chatgpt.dhexx.cn/article/lQtFNP9a.shtml

相关文章

ztree 使用教程

zTree 是一个依靠 jQuery 实现的多功能 “树插件”。被广泛应用在系统的权限管理中&#xff0c;本文讲解zTree的一般应用 zTree 官网 http://www.treejs.cn/v3/main.php#_zTreeInfo 1、zTree 官网下载 ztree 下载好后放到项目相关目录下 2、编写相关代码 引入相关js 、 css …

@PersistenceContext和@Autowired在EntityManager上应用的不同

首先PersistenceContext是jpa专有的注解&#xff0c;而Autowired是spring自带的注释 上方图片的意思就是EntityManager不是线程安全的&#xff0c;当多个请求进来的时候&#xff0c;spring会创建多个线程&#xff0c;而PersistenceContext就是用来为每个线程创建一个EntityMana…

java:spring:注解:@PersistenceContext和@Resource

PersistenceContext private EntityManager em; 注入的是实体管理器&#xff0c;执行持久化操作的&#xff0c;需要配置文件persistence.xml。 注入一堆保存实体类状态的数据结构&#xff0c;针对实体类的不同状态(四种,managedh或detached等)可以做出不同的反应(merge,persis…

@PersistenceContext和@Autowired在EntityManager上应用的区别。

在使用SpringJPA的时候&#xff0c;经常看到如下代码&#xff1a; PersistenceContext private EntityManager entityManager;于是就有些好奇&#xff0c;这个PersistenceContext是几个意思&#xff0c;如果是实体注入的话&#xff0c;统一采用 Autowired不可以吗&#xff1f;…

JAVAEE容器如何管理EntityManager和PersistenceContext

2019独角兽企业重金招聘Python工程师标准>>> 容器托管EntityManager PersistenceContext&#xff0c;存放unitName指向的DataBase对应的EntityBean实例集合&#xff0c;以及对这些实例进行生命周期管理 PersistenceContext( name"entityManagerNa…

An attempt was made to call the method javax.persistence.PersistenceContext.synchronization()

报错 解决办法 1、 2、 3、 4、 5、 别忘了最后点击 Apply 然后在点击ok 重启完事 6、 如果都不行的话 It was loaded from the following location: 就去这个提示下的位置 把它报错的包删除 从新加载Maven即可&#xff01;&#xff01;

Spring各种注解 @PersistenceContext和@Resource @GetMapping、@PostMapping、@PutMapping、@DeleteMapping

这里记录各种spring注解 DataAllArgsConstructorNoArgsConstructorBuilder Data 使用这个注解&#xff0c;就不用再去手写Getter,Setter,equals,canEqual,hasCode,toString等方法了&#xff0c;注解后在编译时会自动加进去。 AllArgsConstructor 使用后添加一个构造函数&…

SpringDataJPA+Hibernate框架源码剖析(六)@PersistenceContext和@Autowired注入EntityManager的区别

SpringDataJPAHibernate框架源码剖析系列文章&#xff1a; SpringDataJPAHibernate框架源码剖析&#xff08;一&#xff09;框架介绍SpringDataJPAHibernate框架源码剖析&#xff08;二&#xff09;框架整合 之 EntityManagerFactory的构建SpringDataJPAHibernate框架源码剖析…

@PersistenceContext 注解在spring中代理

PersistenceContext private EntityManager em;springBoot 2.x 这里注入的是EntityManager的代理类&#xff0c;注入的代理类是单例的&#xff0c;所以是线程安全的 在调用EntityManager的方法时 其实是调用代理类 SharedEntityManagerInvocationHandler中的invoke方法 在这…

JPA之EntityManager踩坑笔记:更改PersistenceContext

一、原因&#xff1a;项目中配置两个Spring JPA的数据源&#xff0c;使用EntityManager的时候默认是选择第一个&#xff0c;导致查询不到第二个数据源的数据。 二、Spring JPA多数据源怎么使用EntityManager 1. Spring JPA多数据源的配置请查看此文章&#xff1a;SpringData …

Spring Data JPA 之 理解 Persistence Context 的核心概念

21 理解 Persistence Context 的核心概念 21.1 Persistence Context 相关核心概念 21.1.1 EntityManagerFactory 和 Persistence Unit 按照 JPA 协议⾥⾯的定义&#xff1a;persistence unit 是⼀些持久化配置的集合&#xff0c;⾥⾯包含了数据源的配置、EntityManagerFacto…

JPA中为什么EntityManager 的注解要用@PersistenceContext

在使用SpringJPA的时候&#xff0c;看到如下代码 PersistenceContextprivate EntityManager entityManager; 于是就有些好奇&#xff0c;这个PersistenceContext是几个意思&#xff0c;如果是实体注入的话&#xff0c;统一采用 Autowired可以吗&#xff1f;于是上网查了下&am…

web打印时,各种页面样式设置

最近碰到这个问题&#xff0c;我需要将网页打印成PDF文件。Chrome可直接将网页保存&#xff08;打印&#xff09;为PDF&#xff08;无需安装Adobe&#xff09;&#xff0c;但式样跟网页上显示的截然不同。我测试了一下用法&#xff0c;了解了其中的一些原理和解决方法&#xff…

WEB免费打印控件推荐

在WEB系统中&#xff0c;打印的确是个烦人的问题。 要么自己开发打印控件&#xff0c;如果项目时间紧&#xff0c;肯定来不及。 要么购买成熟的打印控件&#xff0c;如果是大项目可以考虑&#xff0c;但如果项目只有几K到1、2W之间&#xff0c;这就麻烦了。 前段时间有机会接…

Web打印的实现方法

目前&#xff0c;在做B/S结构程序开发的时候&#xff0c;最棘手和最令人头疼的问题之一就是Web打印。往往打印出来的效果和自己预期的效果相差甚远&#xff0c;那么怎样才能打印出自己想要的效果呢&#xff1f;本文阐述的方法将解决这一问题&#xff0c;从而使得Web打印变得简单…

简单实用的web打印方案-网页精准打印

在当前这个互联网时代&#xff0c;大部分企业都搭建了自已的平台&#xff0c;通过平台联系客户&#xff0c;与粉丝互动&#xff0c;展示自己的产品。PC网站、APP、手机站、这些平台是企业互联网生态系统的重要基础。在公司平台化、系统化的今天&#xff0c;工作中出现web打印的…

JPrint web打印编辑器及web在线打印,JS打印编辑器

效果图 背景&#xff1a; 电子商务的发展火了一大批网商&#xff0c;每日近2000W的订单需要处理&#xff0c;相应的每天有2000W的订单需要打印。在淘宝卖家服务市场里有很多快递单发货单打印工具&#xff0c;他们使用的是阿里提供的菜鸟打印&#xff08;active&#xff09;组件…

前端web打印

前端打印 一、Vue打印插件 第一种方法&#xff1a;通过npm 安装插件 1&#xff0c;安装 npm install vue-print-nb --save 2&#xff0c;引入 安装好以后在main.js文件中引入 import Print from vue-print-nbVue.use(Print); //注册   3&#xff0c;现在就可以使用了 &…

Web Print打印服务

Web Print打印服务 题目一、安装打印服务二、配置相关的打印机三.配置证书并添加到打印机里1.RouterSrv2.IspSrv提示:若需要单独全套笔记可私信我咨询 题目 Web Print 添加一台虚拟打印机,名称为“CS-Print”,发布到AD域。 客户端们都能够通过访问“https://print.worldski…

JS web打印

11.1 Web打印 Web打印是一种常用的打印方式&#xff0c;其使用方法简单、方便、快捷&#xff0c;在浏览网页的同时就可以实现打印的功能。 实例291 调用IE自身的打印功能实现打印 实例说明 通过JavaScript调用IE自身的打印功能实现打印&#xff0c;这种方法比较简单&#xff…