JQuery-zTree.js使用范例

实现Tree树的插件很多,比如常见的UI:Layui、ElementUI、iView ... 。这里我们介绍一个小巧的构建Tree树的插件 zTree.js

zTree.js 官网API介绍的灰常详细了,这里我们实战使用zTree.js构建一棵Tree树。

写在前面
下列文章中讲述的实例,需要使用的后端数据是已经查询好的,这里我们不讲怎么查询数据,只讲如何使用现有的数据构建Tree树,详细的教程请查看我的 GitHub, 如果你觉得写得好,欢迎star呀!!

起步

使用zTree.js首先需要导入zTree的依赖库文件,传送门

由于我使用了基于boostrap主题的zTree,所以还是建议大家去我的GitHub项目地址下载(CSS是修改过的),传送门:GitHub

页面中需要引入如下依赖库文件:

<link rel="stylesheet" href="static/lib/bootstrap.min.css"/>
<link rel="stylesheet" href="static/lib/css/demo.css"/>
<link rel="stylesheet" href="static/lib/css/metroStyle/metroStyle.css"/> <script type="text/javascript" src="static/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="static/lib/jquery.ztree.core.min.js"></script>
<script type="text/javascript" src="static/lib/jquery.ztree.excheck.min.js"></script>

前端构建一棵tree树

查阅zTree.js官网API,构建一棵Tree树很简单:

一、前端初始化一个div,用来展示Tree树

zTree构建的Tree树是用iframe嵌套的,所以不用担心宽度、高度的问题

 <div class="zTreeDemoBackground">
<ul id="tree" class="ztree"></ul>
</div>

初始化的div只需要关注id属性即可,因为JS中会根据这个ID找到构建Tree树的位置。

二、javaScript加载Tree树

为了真实点构建Tree树,我这里用一个json文件来模拟请求后端的数据。在同级目录下创建data.json,在其中写入指定格式的JSON字符串:

 [{  "id": ,
"name": "总经理",
"pid": ,
"parent": true
}, {"id": ,
"name": "技术部",
"pid": ,
"parent": true
}, {
"id": ,
"name": "项目经理",
"pid": ,
"parent": false
}, {"id": ,
"name": "项目组组长",
"pid": ,
"parent": false
}, {
"id": ,
"name": "安全部",
"pid": ,
"parent": true
}, {"id": ,
"name": "网络安全部负责人",
"pid": ,
"parent": false
}, {
"id": ,
"name": "项目安全测试员",
"pid": ,
"parent": false
}]

然后,写JavaScript代码:

 var setting = {
view: {
selectedMulti: true
},
check: {
enable: true,
},
data: {
simpleData: {
enable: true,//是否采用简单数据模式
idKey: "id",//树节点ID名称
pIdKey: "pid",//父节点ID名称
rootPId: -1,//根节点ID
}
}
};
$(function () {
//加载后端构建的ZTree树(节点的数据格式已在后端格式化好了)
$.ajax({
url: 'data.json',
type: 'get',
dataType: "json",
success: (data) => {
console.log(data);
$.fn.zTree.init($("#tree"), setting, data);//初始化树节点时,添加同步获取的数据
},
error: (data) => {
alert(data.message);
}
});
});

解释

  1. setting中包含了ztree的所有配置。
  2. view中包含了Tree树的一些视图样式配置,例如是否显示节点间的连线,是否显示节点的图标,等...
  3. selectedMultiview的一个配置参数,设置是否允许同时选中多个节点。
  4. data中包含了要展示的数据以及展示数据的配置,因为我们采用了ajax请求数据,这里需要配置simpleData
  5. simpleData数据展示的配置:enable是否采用简单的数据模式;idKey树节点ID名称;pIdKey父节点ID名称;rootPId根节点ID

以上参数配置,大家最好去参看zTree.js官网API。

如果配置好了setting,那下面就要ajax请求数据并渲染出来。如上在ajax的success回调函数中使用$.fn.zTree.init($("#treeID"),setting,data)渲染树节点,其中第一个参数:树要渲染的位置、第二个参数:刚才写的setting配置,第三个参数:要加载的数据。

如上,我们先看下效果:

其中我们最该关心的是如何实现节点的渲染,说白了就是要弄明白怎样的数据结构zTree才能渲染出一棵树。

Tree树数据结构分析

首先,zTree渲染节点需要的数据一定是JSON格式的数据,且JSON数据的格式和simpleData配置参数有关;想要使用ajax这种方式渲染节点,你必须开启enable: true,其次idKey是树节点ID名称,也就是说树的每个节点都有一个id,我们在这里要指定被渲染的数据中展示id的名称;其次要指定pIdKey,因为你的节点不会都是平级的没有子节点,当需要子节点,就必须指定一个区分父子节点的ID名称;最后就是rootPId表示根节点ID,即最上层的节点ID,一般写为-1即可。

此时,你或许应该参考一下我这篇文章:Shiro实现权限管理之表结构设计 ,表结构的设计和tree树的构建也算是有一部分的关系吧。

如果你的simpleData是这样配置的:

 simpleData: {
enable: true,//是否采用简单数据模式
idKey: "id",//树节点ID名称
pIdKey: "pid",//父节点ID名称
rootPId: -1,//根节点ID
}

那么你就应该提供这样的JSON数据:

[{"id": "xx", "pid": "xx", "pid": "xx"},{"id": "xx",....},{....}]

只要名称和JSON数据中对应就行,不然无法渲染出节点。

实例

如何实现默认选中

实现默认选中,就是在初始化树的时候,将(用户)已拥有的节点选项选中。要知道所有的节点数据应该是从数据库中读取出出来的,例如这篇博文 权限管理系统数据库表设计 中用户都可能拥有一个角色,那么在遍历角色树的时候就应该默认选中一些节点表述用户已经拥有了这个节点角色。

  • 如何实现默认选中?

简单一句话:遍历需要默认选中的节点数据(ID..),调用zTree.js相关的方法根据(ID)实现默认选中。

首先我们需要了解:

函数 用处
$.fn.zTree.getZTreeObj('') 获取zTree对象,根据div中指定的ID获取此渲染的ZTree对象,下面的方法都用到此对象调用
zTree.selectNode(treeNode,addFlag,isSilent) 根据上面获取的zTree对象调用selectNode,参数一:要选中的节点数据;参数二:是否允许同时选中多个节点;参数三:为false选中节点自动滚动到可视区域,实现选中子节点的父节点默认展开
zTree.checkNode(treeNode,checked,checkTypeFlag,callbackFlag) selectNode只实现选择了节点,checkNode实现勾选节点,参数二:是否勾选节点;参数三:勾选父节点是否联动勾选其下的子节点;参数四:是否自动触发beforeCheck & onCkeck 回调函数
zTree.getNodeByParam(key,value,parentNode) 获取完全匹配节点数据的JSON对象,参数一:要精确匹配的属性名称;参数二:要精确匹配的属性值;参数三:在某个父节点下查找

用法

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="static/lib/bootstrap.min.css">
<link rel="stylesheet" href="static/lib/css/metroStyle/metroStyle.css">
<link rel="stylesheet" href="static/lib/css/demo.css">
</head>
<body>
<div class="zTreeDemoBackground">
<ul id="tree" class="ztree"></ul>
</div>
</body>
<script type="text/javascript" src="static/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="static/lib/jquery.ztree.core.min.js"></script>
<script type="text/javascript" src="static/lib/jquery.ztree.excheck.min.js"></script>
<script type="text/javascript">
var setting = {
view: {
selectedMulti: false
},
check: {
enable: true,
},
data: {
simpleData: {
enable: true,//是否采用简单数据模式
idKey: "id",//树节点ID名称
pIdKey: "pid",//父节点ID名称
rootPId: -1,//根节点ID
}
}
};
$(function () {
//加载后端构建的ZTree树(节点的数据格式已在后端格式化好了)
$.ajax({
url: 'data.json',
type: 'get',
dataType: "json",
success: (data) => {
console.log(data);
$.fn.zTree.init($("#tree"), setting, data);//初始化树节点时,添加同步获取的数据
checkNodes();
},
error: (data) => {
alert(data.message);
}
});
}); //处理默认选中的方法
function checkNodes(){
//模拟数据库中已存在的数据(要实现默认选中的数据)
var data = [{"id": 21, "name": "总经理", "pid": 0},{"id":'27', "name": "项目经理", "pid": 26}]; var zTree = $.fn.zTree.getZTreeObj("tree"); //获取zTree对象
data.forEach(row => {
zTree.selectNode(zTree.getNodeByParam("id", row.id), true, false);
zTree.checkNode(zTree.getNodeByParam("id", row.id), true, false);
});
}
</script>
</html>

如上,实现默认选中,在初始化树后立即调用处理默认选中的方法即可。我们模拟默认选中的数据中包含了id和name以及pid,这些都是比较基础的数据,ztree的selectNodecheckNode方法都是根据id实现选中的,
默认选中要提供的数据和渲染树用的格式是相同的。其中:

  1. getZTreeObj()将根据<div>中定义的id值来获取当前树的对象;
  2. selectNode实现选择节点,不会勾选节点,但是它能实现将被勾选的子节点所在的父节点展开;
  3. checkNode实现勾选节点,设置第三个参数是false,则表示选中父节点时不联动勾选其下的子节点,因为子节点未必都要默认选中。

如何获取选中的节点

获取选中的节点,只需要了解zTree.getCheckedNodes(),用来获取选中节点数据的JSON对象。其中获取到的选中节点数据包含一定顺序:选中父节点永远在选中子节点的最前面。

如果想要在提交表单的时候,将选中节点的值传给后台,就可以使用getCheckedNodes()方法获取到选中节点数据,然后遍历得到各个选中节点的数据。

如何实现单选

实现单选,只需要在settingcheck中配置chkStyle: "radio"即可实现单选,但是,此时实现的单选只在同级节点上才能实现单选,也就是说你在同级节点上只能单选,但是在你可以同时选中子节点和父节点。

那么,在你调用getCheckedNodes()方法获取选中节点数据时,其中也包含了选中的父节点,因为父节点可能只是个分组不一定要存入到数据库中;那么此时你就要判断下如果选中的节点的长度>0,那么就取索引位置的最后一个值;

后端如何封装Tree树结构

上面我们将的都是前端如何将JSON数据渲染成一棵Tree树,但是渲染用的数据应该是冲数据库中读取的。下面我们应该学习一下后端如何实现封装Tree树用的JSON数据。

  • SpringMVC

我们使用SpringMVC作为与后端交互的Web层框架,关于SpringMVC + Spring + Mybatis 框架的整合,大家可以参看我的这个项目 SSM框架整合

封装实体类

想必大家一定知道@ResponseBody这个注解,如果方法或类上添加了这个注解,那么@RequestMapping()映射return的东西将不再是InternalResourcecViewResolver视图解析器解析的视图地址,而是JSON格式的数据。
那么想要让SpringMVC相应一串[{"id": "xx", "name": "", "xx"},{"id": "xx", "name": "xx"}]这种格式的数据,我们就必须手动将数据封装成这种格式,如此SpringMVC才能将对象转换成JSON串。

我们会想到,我们可以将从数据库中读取的数据,依次存入到Map(或List)集合中,然后return map。当然,这是可行的,但是或许麻烦了些,因为整个项目中不止要构建一棵Tree树,每次都要new Map重用率就太低了。所以,一个简单的方式,就是手动创建一个实体类TreeEntity.java用以存放从数据库中读取到的数据,这样每次构建Tree树都能使用这个实体类对象。

TreeEntity.java属性如下:

 public class TreeEntity implements Serializable {
private Long id; //节点的id值
private String name; //节点的名称
private Boolean isParent; //是否是父节点
private Long pid; //当前节点对应父节点的id值 public TreeEntity(Long id, String name, Boolean isParent, Long pid){
this.id = id;
this.name = name;
this.isParent = isParent;
this.pid = pid;
} getter/setter ....
}

如上,你会发现,这是不是和我们前面说的前端构建Tree树的结构是一样的呢。没错,我们前端既然定义了这种格式,后端就必须要给它一个这样格式的数据。

Web层封装Tree数据结构

这里不再讲Dao层中如何查询的数据,我们仅以一个最简单的查询(findAll查询所有)来讲述Tree的数据结构封装。

先看代码:

 @ResponseBody
@RequestMapping("/getZTreeForUserRoles")
public List<TreeEntity> getTreeForUserRoles() {
try {
List<TreeEntity> treeList = new ArrayList<TreeEntity>();
List<Role> roleList = roleService.findAll(); for (Role role : roleList) {
// 为tree树节点添加数据,节点pid为0的都是父节点,其他为子节点
if(role.getPid() != null){
if (role.getPid() == ) {
treeList.add(new TreeEntity(role.getId(), role.getDescription(), true, (long) ));
} else {
treeList.add(new TreeEntity(role.getId(), role.getDescription(), false, role.getPid()));
}
}
}
return treeList;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

解释

  1. 首先要定义映射方法返回的数据类型是List<TreeEntity>;即返回的是一个List集合,但是其中存的是TreeEntity实体类的数据。
  2. 初始化一个空的List集合new ArrayList<TreeEntity>();并调用Service层的方法获取到sys_roles表中的所有数据,当然findAll()方法的返回值也是List集合。
  3. 遍历findAll()查询到的数据;这就体现了返回值是List并且泛型是实体类的优势了,这样我们可以直接通过实体类中定义的setter/getter来存取数据。
  4. 调用TreeEntity中定义的带参构造方法,将3中遍历得到的数据依次循环啊添加到List<TreeEntity>集合中。
  5. List<TreeEntity>集合返回。

我们来看一下这个请求映射返回的数据格式是如何的:

如上,我们已经实现了目的。

拓展

上面的代码中还要说明的就是调用TreeEntity的带参构造函数传入的参数值。我们定义的带参构造函数如下:

 public TreeEntity(Long id, String name, Boolean isParent, Long pid) {
this.id = id;
this.name = name;
this.isParent = isParent;
this.pid = pid;
}

在为List<TreeEntity>集合循环添加值时,要弄清楚:

  1. 节点id是什么?

节点的id是每个节点的唯一标识,就像数据库的主键值一样,所以我们通常将其设置为数据库中的主键值。并且以后也要获取这个主键值。

  1. 节点名称是什么?

节点的名称name是前端展示的各个节点的名称。而这些名称应该和数据库中的值是相同的,所以我们将其设置为数据库的description的值。

  1. 父节点是什么?

父节点,我们在数据库中已经定义了,即数据库中存在一个字段pid,这个字段表示的是上级节点的id值,即如果存在上级节点(或叫上级分组),那么就给此row的pid字段设置为上级row的主键id值。

  1. 如何定义父节点?

根据构造方法中的isParent字段,如果是父节点就直接手动设置为true,否则就设置为false。
如何判断是父节点?根据数据库(实体类)中已有的属性值pid判断,如果pid不为0就表示是子节点,如果pid是0就是父节点(因为主键值不可能为0)。

JQuery-zTree.js使用范例的更多相关文章

  1. C#使用Jquery zTree实现树状结构显示_异步数据加载

    JQuery-Ztree下载地址:https://github.com/zTree/zTree_v3 JQuery-Ztree数结构演示页面:  http://www.treejs.cn/v3/dem ...

  2. 使用ztree.js,受益一生,十分钟学会使用tree树形结构插件

    看到ztree.js,这几个字眼,毋庸置疑,那肯定就是tree树形结构了,曾经的swing年代有jtree,后来jquery年代有jstree和treeview,虽然我没写过,但是我见过,一些小功能做 ...

  3. JQuery ztree 异步加载实践

    本来要做一个文件目录浏览界面,需要遍历所有的文件和目录,很显然一次性读取时很费时费力的一件事情. 因此就需要做异步加载.... 不过网上的几篇帖子还挺坑的!原始参考:JQuery异步加载实例,相对来说 ...

  4. jQuery+zTree加载树形结构菜单

    jQuery+zTree加载树形结构菜单 由于项目中需要设计树形菜单功能,经过一番捣腾之后,终于给弄出来了,所以便记下来,也算是学习zTree的一个总结吧. zTree的介绍: 1.zTree 是利用 ...

  5. Jquery zTree结合Asp.net实现异步加载数据

    zTree结合Asp.net实现异步加载数据 实现简单操作 zTree 下载 api 访问 :http://www.ztree.me/v3/main.php 例子中用到json数据转化 newtons ...

  6. Jquery zTree的使用

    <%@ page language="java" pageEncoding="utf-8"%><%@taglib prefix="s ...

  7. jQuery zTree v3.5 实例3 异步树

    最终效果: 点击非叶子节点时,向后台发送请求,获取下级菜单 前台代码如下: <%@ page language="java" contentType="text/h ...

  8. jquery——zTree, 完美好用的树插件

    Demo 这绝对是我见过最完美的tree了,尽管是国产货,但一点不输国外产品,国外的还没有见过这么强的. _______________________________________________ ...

  9. jquery Ztree v3.5 实例2 自定义显示在节点前的图片

    显示效果如下: 代码如下: <html> <head><title></title></head> <script type=&quo ...

随机推荐

  1. 三天精通Vue--Vue的常用语法

    Vue的介绍 官网教程:https://cn.vuejs.org/v2/guide/installation.html 掘金:https://juejin.im/ cdn(在线的网络连接资源):htt ...

  2. Android Studio 之 Navigation【1.页面之间的切换】

    1.创建 2个 Fragment ,下面两个include 不要勾 2.创建好 Fragment 后,打开layout中的 fragment.xml 文件,将里面默认的 textView 控件删除掉 ...

  3. pyhon项目之后pexpect使用

    pyhon项目之后pexpect使用1.安装pip3.6 install pexpect 实例1 ssh 登陆linux 服务器,并且执行命令 #!/usr/bin/env python3.6# -* ...

  4. 软件工程1916|W(福州大学)_助教博客】个人总结作业(第12次)成绩公示

    1.作业链接 个人作业--软件工程实践总结作业 https://edu.cnblogs.com/campus/fzu/SoftwareEngineering1916W/homework/3316 2. ...

  5. OpenSTF 平台搭建

    什么是OpenSTF? OpenSTF(Smartphone Test Farm)是一个web端移动设备管理平台,可以从浏览器端远程调试.远程管理设备.其实有点类似于我们现在很火热的云测平台,如:te ...

  6. AQS2--出队

    队列不卡死,一定要:前面节点变成头结点唤醒时候能够唤醒后面节点,依次类推. 设置前面节点=-1就是为了前面节点走的时候,唤醒自己. 正常没有阻塞节点,设置前面=-1,再旋转一次尝试获取锁,才阻塞.即使 ...

  7. css3自定义上传图片输入框的方法

    css3自定义上传图片输入框的方法 代码如下<pre> <form class="form1"> <img src="/kelatoupia ...

  8. thinkphp 6.0 swoole扩展websocket使用教程

    前言 ThinkPHP即将迎来最新版本6.0,针对目前越来越流行Swoole,thinkphp也推出了最新的扩展think-swoole 3.0. 介绍 即将推出的tp6.0,已经适配swoole.并 ...

  9. AntDesign vue学习笔记(二)axios使用

    之前在vue页面中引入axios使用,本篇在mainjs中引入,这样就不用单独在每个页面引入 1.mainjs中引入axios,设置基础url import axios from 'axios' ax ...

  10. pychram 激活码

    转自博客:https://blog.csdn.net/may_ths/article/details/84032217 激活码到期时间: 2020.06 K6IXATEF43-eyJsaWNlbnNl ...