Ztree使用总结(一次性加载与异步加载)
ztree树形显示,结构清晰
示例如下:
一次性加载数据:
html:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>[ StaMntr ]</title>
<link rel="stylesheet" type="text/css" th:href="@{/libs/bootstrap/css/bootstrap.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/libs/layout/jquery.layout.1.14.css}"/>
<link th:href="@{/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>
<style>
.ui-layout-east .btn-abnormal {
margin: 10px 0;
width: 100%;
}
.btn:focus, .btn:active:focus {
outline: 0px;
}
ul.ztree {
margin-top: 10px;
border: 1px solid #617775;
width: 600px;
height: 450px;
overflow-y: scroll;
overflow-x: auto;
}
div.zTreeDemoBackground {
width: 600px;
height: 450px;
text-align: left;
}
span.search_highlight {
color: whitesmoke;
background-color: darkred;
</style>
</head>
<body style="background:#000;">
<div style="width: 600px">
<input id="keyword" type="search" placeHolder="搜索关键字"/>
</div>
<div class="content_wrap">
<div class="zTreeDemoBackground left">
<ul id="tree" class="ztree"></ul>
</div>
</div>
<script type="text/javascript" th:src="@{/js/jquery-1.11.0.min.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js}"></script>
<!--
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js}"></script>
-->
<script type="text/javascript">
var zNodes ;
//ztree配置
var setting = {
async:
{
autoParam:[],//异步加载需要带的查询参数
contentType:"application/x-www-form-urlencoded",//Ajax 提交参数的数据类型。[setting.async.enable = true 时生效]
//默认值:"application/x-www-form-urlencoded"
dataType:"text",//ajax请求返回的数据类型
enable:false,//是否是异步请求
type:"post",//ajax请求类型
url:""//ajax请求的地址
},
callback:
{
beforeAsync:null,//异步请求前的回调函数
beforeClick:null,//点击前回调函数
onAsyncSuccess:null,//异步请求成功回调函数
onClick:null,//单击时回调函数
},
data:
{
keep:
{
leaf:false,
parent:false
},
key:
{
name:"name",
title:" ",
url:"url"
},
simpleData:
{
enable:true,
idKey:"id",
pIdKey:"pId",
rootPId:"0"
}
},
view:
{
fontCss:{color:"white"}, //文字样式
showIcon: true,
showLine: true,
ShowTitle: true,
nameIsHTML: true,
expandSpeed: "slow"
}
};
$(function() {
var url = "/function/tree/testRequestData";
$.ajax({
type: "GET",
url: url,
data: {
},
success: function(data) {
initThisZtree(data);
},
error:function(){
}
});
});
/**
* 初始化ztree
*
* @param {Object} data
*/
function initThisZtree(data){
//初始化ztree三个参数分别是(jQuery对象,ztree设置,树节点数据)
var treeObj = $.fn.zTree.init($("#tree"), setting, data);
//treeObj.expandAll(true); //将所有节点展开
}
function zOnClick(event, treeId, treeNode) {
var treeId = treeNode.id;
var treeName = treeNode.name;
$("#treeId").val(treeId);
$("#treeName").val(treeName);
var url = $("#mainframe").attr("src");
if(url.indexOf("?stId") > -1){
url = url.split("?")[0];
}
url = url + "?stId=" +treeId;
$("#mainframe").attr("src",url);
}
</script>
</body>
</html>
后台:
后台就是正常controller,接收前端前后,获取节点数据。
@GetMapping("/testRequestData")
@ResponseBody
public List<ZTreeNode> testTreeData() {
HttpSession httpSession = ServletUtils.getSession();
String userArea = (String)httpSession.getAttribute("userArea");
if(userArea == null || userArea.equals("")) {
userArea = "113715890591105063";
//113715891161530369 113715890591105063
}
//List<ZTreeNode> list = treeNodeQuery.getTreeDatasById(userArea);
List<ZTreeNode> list = treeNodeQuery.getExpandTreeDatasById(userArea);
return list;
}
具体的后台查库获取节点信息就不写了,暂无通用性
异步加载:
html:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>[ StaMntr ]</title>
<link rel="stylesheet" type="text/css" th:href="@{/libs/bootstrap/css/bootstrap.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/libs/layout/jquery.layout.1.14.css}"/>
<link th:href="@{/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>
<style>
.ui-layout-east .btn-abnormal {
margin: 10px 0;
width: 100%;
}
.btn:focus, .btn:active:focus {
outline: 0px;
}
ul.ztree {
margin-top: 10px;
border: 1px solid #617775;
width: 600px;
height: 450px;
overflow-y: scroll;
overflow-x: auto;
}
div.zTreeDemoBackground {
width: 600px;
height: 450px;
text-align: left;
}
span.search_highlight {
color: whitesmoke;
background-color: darkred;
</style>
</head>
<body style="background:#000;">
<div style="width: 600px">
<input id="keyword" type="search" placeHolder="搜索关键字"/>
</div>
<div class="content_wrap">
<div class="zTreeDemoBackground left">
<ul id="tree" class="ztree"></ul>
</div>
</div>
<script type="text/javascript" th:src="@{/js/jquery-1.11.0.min.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js}"></script>
<!--
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js}"></script>
-->
<script type="text/javascript">
var zNodes ;
//ztree配置
var setting = {
async: {
enable: true,
type:"get",
url:"/function/tree/asyncRequestData",
autoParam:["id", "level"],
dataFilter: filter
},
data:{
simpleData:{
enable: true,
idKey:'id',
pIdKey:'pid',
rootPId: 0
}
},
view:
{
fontCss:{color:"white"}, //文字样式
showIcon: true,
showLine: true,
ShowTitle: true,
nameIsHTML: true,
expandSpeed: "slow"
}
};
$(document).ready(function(){
initZTree();
});
function filter(treeId, parentNode, childNodes) {
return childNodes;
}
//初始化树
function initZTree(){
$.ajax({
url:"/function/tree/testRequestData",
type:"get",
dataType: "json",
success: function(data){
console.log(data);
var zTreeObj = $.fn.zTree.init($("#tree"),setting, data);
//让第一个父节点展开
//zTreeObj.expandAll(true);
//展开一级节点
var nodes0 = zTreeObj.getNodesByParam("level", "0");
for(var i=0; i<nodes0.length; i++){
zTreeObj.expandNode(nodes0[i], true);
}
//展开二级节点
var nodes1 = zTreeObj.getNodesByParam("level", "1");
for(var i=0; i<nodes1.length; i++){
zTreeObj.expandNode(nodes1[i], true);
}
},
error: function(){
}
});
}
</script>
</body>
</html>
后台:
异步加载后台,分为两步:
1.初始ajax请求,获取根节点,或者自定义想一次性展开的节点数据
2.根据上面最底层以后的数据实现异步加载,通过传入节点的id及level
如下:
第一步如下:
@GetMapping("/testRequestData")
@ResponseBody
public List<ZTreeNode> testTreeData() {
HttpSession httpSession = ServletUtils.getSession();
String userArea = (String)httpSession.getAttribute("userArea");
if(userArea == null || userArea.equals("")) {
userArea = "113715890591105063";
//113715891161530369 113715890591105063
}
//List<ZTreeNode> list = treeNodeQuery.getTreeDatasById(userArea);
List<ZTreeNode> list = treeNodeQuery.getExpandTreeDatasById(userArea);
return list;
}
第二步,异步加载:
@GetMapping("/asyncRequestData")
@ResponseBody
public List<ZTreeNode> asyncRequestData() {
String id = ServletUtils.getParameter("id");
String level = ServletUtils.getParameter("level");
List<ZTreeNode> list = treeNodeQuery.getAsyncTreeDatasById(id, level);
return list;
}
异步加载,带上搜索功能
html:
<!--
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<title>[ StaMntr ]</title>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
window.location.href="/function/wf/index/zh9000";
</script>
</body>
</html>
-->
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>[ StaMntr ]</title>
<link rel="stylesheet" type="text/css" th:href="@{/libs/bootstrap/css/bootstrap.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/libs/layout/jquery.layout.1.14.css}"/>
<link th:href="@{/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>
<style>
.ui-layout-east .btn-abnormal {
margin: 10px 0;
width: 100%;
}
.btn:focus, .btn:active:focus {
outline: 0px;
}
body{height:auto;font-family: "Microsoft YaHei";}
button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
</style>
</head>
<body style="background:#000;">
<div class="ui-layout-west" >
<div id="btnWarn" style="display:none;">
<div class="treeSearchInput" id="search">
<label for="keyword" style="color:white">关键字:</label>
<input id="search_content" type="text" value="" name="param"/>
<!--
<input type="text" class="empty" id="keyword" maxlength="50">
<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
-->
</div>
<div id="tree" class="ztree treeselect" ></div>
</div>
</div>
<div class="ui-layout-center" style="padding:0px;overflow:hidden;">
<iframe class="mainIframe" id="mainIframe" width="100%" height="100%" src="" frameborder="0"></iframe>
</div>
<script type="text/javascript" th:src="@{/js/jquery-1.11.0.min.js}"></script>
<script type="text/javascript" th:src="@{/libs/layout/jquery.layout.1.14.js}"></script>
<!--
<script type="text/javascript" th:src="@{/js/ry-ui.js?v=2.4.0}"></script>
-->
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js}"></script>
<script type="text/javascript">
var userArea='[[${userArea}]]';
var url = '[[${url}]]';
$(function(){
$("body").layout();
$('#btnWarn').show();
$('#mainIframe').attr('src',url);
});
var setting = {
async: {
enable: true,
type:"get",
url:"/function/tree/asyncRequestData",
autoParam:["id", "level"],
dataFilter: filter
},
data:{
simpleData:{
enable: true,
idKey:'id',
pIdKey:'pid',
rootPId: 0
}
},
callback:{
onClick : zOnClick,
onNodeCreated: zTreeOnNodeCreated
},
view:
{
fontCss:{color:"white"}, //文字样式
showIcon: true,
showLine: true,
ShowTitle: true,
nameIsHTML: true,
expandSpeed: "slow"
}
};
$(document).ready(function(){
initZTree();
});
function filter(treeId, parentNode, childNodes) {
return childNodes;
}
//初始化树
function initZTree(){
$.ajax({
url:"/function/tree/testRequestData",
type:"get",
dataType: "json",
success: function(data){
console.log(data);
var zTreeObj = $.fn.zTree.init($("#tree"),setting, data);
//让第一个父节点展开
//zTreeObj.expandAll(true);
//展开一级节点
var nodes0 = zTreeObj.getNodesByParam("level", "0");
for(var i=0; i<nodes0.length; i++){
zTreeObj.expandNode(nodes0[i], true);
}
//展开二级节点
var nodes1 = zTreeObj.getNodesByParam("level", "1");
for(var i=0; i<nodes1.length; i++){
zTreeObj.expandNode(nodes1[i], true);
}
},
error: function(){
}
});
}
function zOnClick(event, treeId, treeNode) {
var pNode = treeNode.getParentNode();
var ppNode = pNode.getParentNode();
console.log("当前节点的id:------"+treeNode.id);
console.log("父节点的id:------"+ pNode.id);
console.log("祖父节点的id:------"+ ppNode.id);
var url = $("#mainIframe").attr("src");
console.log(url);
if(url.indexOf("?devId") > -1){
url = url.split("?")[0];
}
url = url + "?devId=" + treeNode.id;
$("#mainIframe").attr("src",url);
}
//搜索功能
$("#search_content").on('keypress', function (event) {
if (event.keyCode == 13) {
searchM();
}
});
function searchM() {
var param = $.trim($("input[name='param']").val());
var treeObj = $.fn.zTree.getZTreeObj("tree");
var node = treeObj.getNodeByParam("name", param, null);
if(param != ""){
param = encodeURI(encodeURI(param));
treeObj.setting.async.otherParam=["param", param];
}else {
//搜索参数为空时必须将参数数组设为空
treeObj.setting.async.otherParam=[];
}
treeObj.selectNode(node); //让搜索节点在可视区域内
treeObj.reAsyncChildNodes(node, "refresh");
}
function zTreeOnNodeCreated(event, treeId, treeNode) {
var param = $.trim($("input[name='param']").val());
var treeObj = $.fn.zTree.getZTreeObj("tree");
//只有搜索参数不为空且该节点为父节点时才进行异步加载
if(param != "" && treeNode.isParent){
treeObj.reAsyncChildNodes(treeNode, "refresh");
}
};
</script>
</body>
</html>
后台和异步加载一样,搜索功能不涉及后台逻辑。
附录:
带上ztreeNode.java源码:
public class ZTreeNode implements Serializable{
private static final long serialVersionUID = 5886322299632761687L;
public String id;
public String pId;
public String name; // 名称
public boolean open=false;
public String file;
public Boolean isParent;
public String getpId() {
return pId;
}
public void setpId(String pId) {
this.pId = pId;
}
public Boolean getIsParent() {
return isParent;
}
public void setIsParent(Boolean isParent) {
this.isParent = isParent;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPId() {
return pId;
}
public void setPId(String id) {
pId = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean getOpen() {
return open;
}
public void setOpen(boolean open) {
this.open = open;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
public ZTreeNode(){
}
public ZTreeNode(String id,String pId,String name,String file){
this.id=id;
this.pId=pId;
this.name=name;
this.file=file;
}
}
如果节点属性有拓展,可以通过,新建类来继承ztreeNode类。
拼音搜索–亲测可行
<!--
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<title>[ StaMntr ]</title>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
window.location.href="/function/wf/index/zh9000";
</script>
</body>
</html>
-->
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>[ StaMntr ]</title>
<link rel="stylesheet" type="text/css" th:href="@{/libs/bootstrap/css/bootstrap.css}"/>
<link rel="stylesheet" type="text/css" th:href="@{/libs/layout/jquery.layout.1.14.css}"/>
<link th:href="@{/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>
<style>
.ui-layout-east .btn-abnormal {
margin: 10px 0;
width: 100%;
}
.btn:focus, .btn:active:focus {
outline: 0px;
}
body{height:auto;font-family: "Microsoft YaHei";}
button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
</style>
</head>
<body style="background:#000;">
<div class="ui-layout-west" >
<div id="btnWarn" style="display:none;">
<div class="treeSearchInput" id="search">
<label for="keyword" style="color:white">关键字:</label>
<input id="search_content" type="text" value="" name="param"/>
<!--
<input type="text" class="empty" id="keyword" maxlength="50">
<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
-->
</div>
<div id="tree" class="ztree treeselect" ></div>
</div>
</div>
<div class="ui-layout-center" style="padding:0px;overflow:hidden;">
<iframe class="mainIframe" id="mainIframe" width="100%" height="100%" src="" frameborder="0"></iframe>
</div>
<script type="text/javascript" th:src="@{/js/jquery-1.11.0.min.js}"></script>
<script type="text/javascript" th:src="@{/libs/layout/jquery.layout.1.14.js}"></script>
<script type="text/javascript" th:src="@{/js/PinYin.js}"></script>
<!--
<script type="text/javascript" th:src="@{/js/ry-ui.js?v=2.4.0}"></script>
-->
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.core-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.excheck-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exedit-3.5.js}"></script>
<script type="text/javascript" th:src="@{/libs/jquery-ztree/3.5/js/jquery.ztree.exhide-3.5.js}"></script>
<script type="text/javascript">
var userArea='[[${userArea}]]';
var url = '[[${url}]]';
$(function(){
$("body").layout();
$('#btnWarn').show();
$('#mainIframe').attr('src',url);
});
var setting = {
async: {
enable: true,
type:"get",
url:"/function/tree/asyncRequestData",
autoParam:["id", "level"],
dataFilter: filter
},
data:{
simpleData:{
enable: true,
idKey:'id',
pIdKey:'pid',
rootPId: 0
}
},
callback:{
onClick : zOnClick,
onNodeCreated: zTreeOnNodeCreated
},
view:
{
//fontCss:{color:"white"}, //文字样式
fontCss:setHighlight,
showIcon: true,
showLine: true,
ShowTitle: true,
nameIsHTML: true,
expandSpeed: "slow"
}
};
$(document).ready(function(){
initZTree();
});
function filter(treeId, parentNode, childNodes) {
return childNodes;
}
//初始化树
function initZTree(){
$.ajax({
url:"/function/tree/testRequestData",
type:"get",
dataType: "json",
success: function(data){
console.log(data);
var zTreeObj = $.fn.zTree.init($("#tree"),setting, data);
//让第一个父节点展开
//zTreeObj.expandAll(true);
//展开一级节点
var nodes0 = zTreeObj.getNodesByParam("level", "0");
for(var i=0; i<nodes0.length; i++){
zTreeObj.expandNode(nodes0[i], true);
}
//展开二级节点
var nodes1 = zTreeObj.getNodesByParam("level", "1");
for(var i=0; i<nodes1.length; i++){
zTreeObj.expandNode(nodes1[i], true);
}
},
error: function(){
}
});
}
function zOnClick(event, treeId, treeNode) {
var pNode = treeNode.getParentNode();
var ppNode = pNode.getParentNode();
console.log("当前节点的id:------"+treeNode.id);
console.log("父节点的id:------"+ pNode.id);
console.log("祖父节点的id:------"+ ppNode.id);
var url = $("#mainIframe").attr("src");
console.log(url);
if(url.indexOf("?devId") > -1){
url = url.split("?")[0];
}
url = url + "?devId=" + treeNode.id;
$("#mainIframe").attr("src",url);
}
//搜索功能
$("#search_content").on('keypress', function (event) {
if (event.keyCode == 13) {
var value = $('#search_content').val();
searchNodeLazy(value);
}
});
function zTreeOnNodeCreated(event, treeId, treeNode) {
var param = $.trim($("input[name='param']").val());
var treeObj = $.fn.zTree.getZTreeObj("tree");
//只有搜索参数不为空且该节点为父节点时才进行异步加载
if(param != "" && treeNode.isParent){
treeObj.reAsyncChildNodes(treeNode, "refresh");
}
};
//模糊查询
var oValue;
function searchNode(value) {
var zTree = $.fn.zTree.getZTreeObj("tree");
if (oValue == value) {
return;
}
oValue = value;
// 关闭所有节点的高亮
// 使用API transformToArray获取所有的节点,getNodes()只能获得根节点,属性children也只能获取下一级节点
var allNodes = zTree.transformToArray(zTree.getNodes());
for (var i = 0; i < allNodes.length; i++) {
// 关闭高亮是利用节点属性highlight来控制fontCss实现的
// 需要配合setting.view中设置的fontCss使用,后面代码会说
allNodes[i].highlight = false;
// 更新节点,因为hightlight改变了,使用updateNode可以更新节点
zTree.updateNode(allNodes[i]);
}
// 先关闭所有节点
zTree.expandAll(false);
// 展开根节点(如果不展开根节点,下面的节点无法展开,不知道是不是bug)
zTree.expandNode(zTree.getNodes()[0], true);
if (value == "") {
return;
}
// 获取与value匹配的节点,使用的ztreeAPI getNodesByParamFuzzy
var nodes = zTree.getNodesByParamFuzzy("name", value);
//拼音模糊搜索
for (var i = 0; i < allNodes.length; i++) {
var shouzimu = $PinYin.searchCap(allNodes[i].name).toLowerCase()
var val = value.toLowerCase();
if (shouzimu.indexOf(val) != -1) {
allNodes[i].highlight = true;
zTree.updateNode(allNodes[i]); // 更新节点,让高亮生效
zTree.expandNode(allNodes[i].getParentNode(), true);
}
}
// 高亮并展开搜索到的节点
for (var i = 0; i < nodes.length; i++) {
nodes[i].highlight = true;
zTree.updateNode(nodes[i]); // 更新节点,让高亮生效
// 展开搜索到的节点的父节点
zTree.expandNode(nodes[i].getParentNode(), true);
}
}
// 有输入后定时执行一次,如果上次的输入还没有被执行,那么就取消上一次的执行
var timeoutId = null;
function searchNodeLazy(value) {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(function() {
searchNode(value);
}, 500);
}
// 设置高亮字体
function setHighlight(treeId, treeNode) {
return (treeNode.highlight) ? {
color : "green",
"font-weight" : "bold",
"background-color" : "#ddd"
} : {
color : "white",
"font-weight" : "normal",
"background-color" : "#000"
};
}
</script>
</body>
</html>