jQuery树形控件zTree使用小结


Posted in Javascript onAugust 02, 2016

0 zTree简介 

树形控件的使用是应用开发过程中必不可少的。zTree 是一个依靠 jQuery 实现的多功能 “树插件”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。 

0.0 zTree的特点
 •最新版的zTree将核心代码按照功能进行了分割,不需要的代码可以不用加载,如普通使用只需要加载核心的jquery.ztree.core-3.5.js,需要使用勾选功能加载jquery.ztree.excheck-3.5.min.js,需要使用编辑功能加载jquery.ztree.exedit-3.5.min.js
 •采用了延迟加载技术,上万节点轻松加载,即使在 IE6 下也能基本做到秒杀
 •兼容 IE、FireFox、Chrome、Opera、Safari 等浏览器
 •支持 JSON 数据
 •支持静态 和 Ajax 异步加载节点数据
 •支持任意更换皮肤 / 自定义图标(依靠css)
 •支持极其灵活的 checkbox 或 radio 选择功能
 •提供多种事件响应回调
 •灵活的编辑(增/删/改/查)功能,可随意拖拽节点,还可以多节点拖拽
 •在一个页面内可同时生成多个 Tree 实例
 •简单的参数配置实现,灵活多变的功能

0.1 zTree文件介绍
 从zTree官网下载的zTree包括以下组成部分 

jQuery树形控件zTree使用小结

•metroStyle文件夹:zTree的metro风格样式相关文件(图片及css样式表)。
•zTreeStyle文件夹:zTree的标准风格样式文件夹(图片及css样式表)
•js文件:zTree.all.js是完整的js库,可单纯加载此文件实现所有zTree功能,ztree.core、ztree.excheck、ztree.exedit、ztree.exhide是对ztree按照功能进行的分割,分别对应基本功能、复选功能、编辑功能、显隐功能。 

1 zTree的基本使用

1.0 zTree的创建
在页面中添加对zTree的js及css引用,由于zTree基于JQuery,JQuery的引用是必须的。 

<!DOCTYPE html>
<HTML>
<HEAD>
 <TITLE> ZTREE DEMO </TITLE>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 <link rel="stylesheet" href="zTreeStyle/zTreeStyle.css" type="text/css">
 <script type="text/javascript" src="jquery-1.4.2.js"></script>
 <script type="text/javascript" src="jquery.ztree.core-3.x.js"></script>
 <SCRIPT LANGUAGE="JavaScript">
 var zTreeObj;
 var setting = {}; // zTree 的参数配置,后面详解
  var zNodes = [  // zTree 的数据属性,此处使用标准json格式
  {
  name: "test1", open: true, children: [
  { name: "test1_1" }, { name: "test1_2" }]
 },
 {
  name: "test2", open: true, children: [
  { name: "test2_1" }, { name: "test2_2" }]
 }
 ];
 $(document).ready(function () {
  zTreeObj = $.fn.zTree.init($("#treeDemo"), setting, zNodes); //初始化zTree,三个参数一次分别是容器(zTree 的容器 className 别忘了设置为 "ztree")、参数配置、数据源
 });
 </SCRIPT>
</HEAD>
<BODY>
 <div>
 <ul id="treeDemo" class="ztree"></ul> 
 </div>
</BODY>
</HTML>

运行结果如下

jQuery树形控件zTree使用小结 

1.1 zTree的配置
zTree的配置采用Json格式,按照配置的类型分为view(可视界面相关配置)、data(数据相关配置)、check(复选框相关配置)、callback(各类事件的回调函数配置)、async(zTree异步加载配置),一下是我们经常会使用到的一些配置及说明,其他详细配置可以参考zTree官方API文档的详细介绍。 

var setting = {
  view: {
  selectedMulti: true, //设置是否能够同时选中多个节点
  showIcon: true, //设置是否显示节点图标
  showLine: true, //设置是否显示节点与节点之间的连线
  showTitle: true, //设置是否显示节点的title提示信息
  },
  data: {
   simpleData: {
   enable: false, //设置是否启用简单数据格式(zTree支持标准数据格式跟简单数据格式,上面例子中是标准数据格式)
   idKey: "id", //设置启用简单数据格式时id对应的属性名称
   pidKey: "pId" //设置启用简单数据格式时parentId对应的属性名称,ztree根据id及pid层级关系构建树结构
  }
  },
  check:{
  enable: true  //设置是否显示checkbox复选框
  },
  callback: {
  onClick: onClick,  //定义节点单击事件回调函数
  onRightClick: OnRightClick, //定义节点右键单击事件回调函数
  beforeRename: beforeRename, //定义节点重新编辑成功前回调函数,一般用于节点编辑时判断输入的节点名称是否合法
  onDblClick: onDblClick, //定义节点双击事件回调函数
  onCheck: onCheck  //定义节点复选框选中或取消选中事件的回调函数
  },
  async: {
  enable: true,   //设置启用异步加载
  type: "get",   //异步加载类型:post和get
  contentType: "application/json", //定义ajax提交参数的参数类型,一般为json格式
  url: "/Design/Get",  //定义数据请求路径
  autoParam: ["id=id", "name=name"] //定义提交时参数的名称,=号前面标识节点属性,后面标识提交时json数据中参数的名称
  }
 };

需要注意的是,zTree的事件回调部分,基本上每一个事件都对应一个beforeXXX事件,比如onClick事件对应有一个beforeOnClick事件,主要用于控制相关事件是否允许执行,如果before事件返回false,则取消执行对应相关事件。 

1.2 zTree的数据格式
 zTree的每一个节点都是一个treeNode对象,treeNode对象经常用到的属性和方法如下: 

treeNode: {
  name, //节点显示的文本
  checked, //节点是否勾选,ztree配置启用复选框时有效
  open, //节点是否展开
  icon, //节点的图标
  iconOpen, //节点展开式的图标
  iconClose, //节点折叠时的图标
  id,  //节点的标识属性,对应的是启用简单数据格式时idKey对应的属性名,并不一定是id,如果setting中定义的idKey:"zId",那么此处就是zId
  pId, //节点parentId属性,命名规则同id
  children, //得到该节点所有孩子节点,直接下级,若要得到所有下属层级节点,需要自己写递归得到
  isParent, //判断该节点是否是父节点,一般应用中通常需要判断只有叶子节点才能进行相关操作,或者删除时判断下面是有子节点时经常用到。
  getPath() //得到该节点的路径,即所有父节点,包括自己,此方法返回的是一个数组,通常用于创建类似面包屑导航的东西A-->B-->C 
  }

zTree的数据源一般有标准数据格式、简单数据格式两种,标准数据格式通过指定节点的chidren属性构建层级关系,而简单数据格式根据根据id,pid属性构建层级关系,我们在应用开发中使用关系型数据库,一般采用的都是简单数据格式。
 标准数据格式

var nodes = [
 {name: "父节点1", children: [
 {name: "子节点1"},
 {name: "子节点2"}
 ]}
];

简单数据格式

var nodes = [
 {id:1, pId:0, name: "父节点1"},
 {id:11, pId:1, name: "子节点1"},
 {id:12, pId:1, name: "子节点2"}
];

注意zTree的默认配置是不启用简单数据格式,使用简单数据格式一定要在setting中进行简单数据格式的相关配置。 

1.3 zTree的常用方法
zTree的主要操作方法介绍如下 
获取zTree对象:var treeObj = $.fn.zTree.getZTreeObj("tree");
增加节点:addNodes(parentNode,index,newNodes,isSlient)

parentNode:指定的父节点,如果增加根节点,请设置 parentNode 为 null 即可

index:新节点插入的位置(从 0 开始),index = -1 时,插入到最后,此参数可忽略

newNodes:需要增加的节点数据 JSON 对象集合,数据只需要满足 zTree 的节点数据必需的属性即可 

isSilent:true 时,添加节点后不展开父节点,其他值或缺省状态都自动展开

 勾选或取消勾选全部节点:checkAllNodes(checked);
 checked参数为true时全部勾选,为false时全部取消勾选。
 勾选或取消勾选单个节点:checkNode(node, checked, checkedTypeFlag,callbackFlag);
 node:要进行操作的节点
 checked:为true勾选,为false取消勾选
 checkeTypeFlag:为true表示对当前结点的子节点及父节点进行勾选状态的联动,为false不联动
 callbackFlag:为true时表示执行beforeOnCheck和onCheck事件的回调函数,为false不执行
 编辑节点
 edit(node);  使节点处于编辑状态,必须引用jquery.ztree.exedit 扩展。
 展开或折叠全部节点:expandAll(expand);
 expand为true是展开所有节点,为false是折叠所有节点。
 根据节点属性查找结点:getNodesByParam(key,value, parentNode);
 key:属性名
 value:属性值
 parentNode:是否在指定节点下查找,为null表示整个树查找。
 获取被勾选或未被勾选的节点集合:getCheckedNodes(checked);
 checked为true表示获取所有被勾选的节点集合,为false表示所有未被勾选的节点集合
 获取输入框勾选状态被改变的节点集合:getChangeCheckedNodes()

2 zTree的常用操作
2.0 ajax请求数据并创建zTree 

$(function () {
  var setting = {   //此处根据自己需要进行配置
  view: {
   selectedMulti: false
  },
  data: {
   simpleData: {
   enable: true
   }
  },
  callback: {
   onClick: onDesignTreeClick,
   onRightClick: OnRightClick,
   beforeRename: beforeRename,   onCheck:onCheck
  }
  };
  $.ajax({
  type: "Get",
  url: "/Design/GetDesignTreeData",   //ajax请求地址
   success: function (data) {
   $.fn.zTree.init($("#treeZo"), setting, data); //加载数据
  },
  });
 });

后台代码如下,可以根据需要返回你想要的任何数据,绑定到zTree上,然后通过treeNode.属性名取到对应的值,实现一些界面逻辑操作。 

public ActionResult GetDesignTreeData()
 {
  var result = _designAppService.GetDesignTreeData();
  List<ModelTreeViewModel> treeModels = new List<ModelTreeViewModel>();
  bool open = false;
  foreach (var design in result.Designs)
  {
  if (design.ParentId == Guid.Empty)
   open = true;
  else open = false;
  treeModels.Add(new ModelTreeViewModel() { Id = design.Id.ToString(), PId = design.ParentId.ToString(), Name = design.Name, Open = open, Data = design.Remarks ?? "", ViewPoint = design.ViewPoint ?? "", Checked = true });
  }
  return Json(treeModels, JsonRequestBehavior.AllowGet);
 }

2.1 节点单击操作
 节点单击事件会捕获事件对象e,zTree的唯一标识treeId,当前选中的节点对象treeNode三个参数。根据实际需求可获取treeNode中包含的任何属性数据,进行相关操作 

function onClick(e, treeId, treeNode) {
  if (treeNode.isParent) //如果不是叶子结点,结束
  return;
  alert(treeNode.name); //获取当前结点上的相关属性数据,执行相关逻辑
 };

2.2 节点复选框事件 

一般情况下我们会直接使用treeObj.getCheckedNodes(true);获取所有选中的节点,然后遍历所有选中的节点进行相关操作,当面对大数据量时,这种操作方法便不可取,可通过getChangeCheckedNodes()方法获取勾选状态被改变的节点集合,值针对状态改变的节点做相应处理。

function onCheck() {
  var treeObj = $.fn.zTree.getZTreeObj("treeDemo"); //获取树对象
  var nodes = treeObj.getChangeCheckedNodes(); //获取勾选状态改变的节点
  var designIds = [];
  var status = 0;     //定义初始勾选状态为未勾选
  if (nodes[0].checked)
  status = 1;     //如果状态改变节点为勾选状态,说明当前操作是从未勾选变为已勾选。
  $.each(nodes, function (i, item) {
  designIds.push(item.id);   //将状态改变的节点id输出到数组
   item.checkedOld = item.checked;  //这句话很关键,将节点的初始状态置为当前状态。否则每次勾选操作获取状态改变节点时只会跟树初始化的状态相比较。
  })
  $.ajax({
  type: "Post",
  url: "/Design/GetRelationComponentIdsByDesigns",
  data: { "designIds": designIds },
  success: function (data) {
   RealBimOcx.BatchAddSubClrInfoBegin();
   $.each(data.result, function (i, item) {
   if (status == 1)      //这里根据发生改变的节点是勾选还是为勾选进行相关逻辑操作。
    RealBimOcx.AddSubClrInfo(item, 255, 255, 0);
   else
    RealBimOcx.AddSubClrInfo(item, 0, 255, 0);
   if (i % 100 == 0) {
    RealBimOcx.BatchAddSubClrInfoEnd();
    RealBimOcx.BatchAddSubClrInfoBegin();
   }

   })
   RealBimOcx.BatchAddSubClrInfoEnd();

  }
  })
 };

2.3 实现zTree的右键增删改操作
首先定义右键弹出面板 

<div id="rMenu" style="z-index:100;">
 <ul>
  <li id="m_add" onclick="addTreeNode();">新增节点</li>
  <li id="m_del" onclick="removeTreeNode();">删除节点</li>
  <li id="m_edit" onclick="editTreeNode();" style="border-bottom:1px solid #cecece">编辑节点</li><li id="m_left">升级</li>
  <li id="m_right">降级</li>
  <li id="m_up">上移</li>
  <li id="m_down" style="border-bottom:1px solid #cecece">下移</li>
  <li id="m_reset" onclick="resetTree();">重置节点</li> <li id="m_open" onclick="treeOpen()">展开所有</li>
  <li id="m_stop" onclick="treeStop()">收起所有</li>
 </ul>
</div>

jQuery树形控件zTree使用小结

实现zTree右键单击事件回调函数 

//右键单击回调函数
 function OnRightClick(event, treeId, treeNode) {
  $("#treeZo").hide();
  if (!treeNode && event.target.tagName.toLowerCase() != "button" && $(event.target).parents("a").length == 0) {
  zTree.cancelSelectedNode();
  showRMenu("root", event.clientX, event.clientY); //根据鼠标位置显示右键操作面板
  } else if (treeNode && !treeNode.noR) {
  zTree.selectNode(treeNode);
  showRMenu("node", event.clientX, event.clientY);
  }
  $("#treeZo").show();
 }
 //根据节点类型,控制右键操作菜单哪些可用哪些不可用
 function showRMenu(type, x, y) {
  $("#rMenu ul").show();
  if (type == "root") {
  $("#m_del").hide();
  $("#m_edit").hide();
  $("#m_left").hide();
  $("#m_right").hide();
  $("#m_up").hide();
  $("#m_down").hide();
  $("#m_add").addClass('mboder');
  } else {
  $("#m_del").show();
  $("#m_edit").show();
  $("#m_left").show();
  $("#m_right").show();
  $("#m_up").show();
  $("#m_down").show();
  $("#m_add").removeClass('mboder');
  }
  rMenu.css({ "top": y + "px", "left": x + "px", "visibility": "visible" });
  $("body").bind("mousedown", onBodyMouseDown);
 }
 //以藏右键面板
 function hideRMenu() {
  if (rMenu) rMenu.css({ "visibility": "hidden" });
  $("body").unbind("mousedown", onBodyMouseDown);
 }
 //单击页面其他位置 隐藏右键面板
 function onBodyMouseDown(event) { 
  if (!(event.target.id == "rMenu" || $(event.target).parents("#rMenu").length > 0)) {
  rMenu.css({ "visibility": "hidden" });
  }
 }

新增节点 

//增加节点
 function addTreeNode() {
  hideRMenu();
  var name = new Date().getTime(); //利用时间戳生成节点名称,保证节点名称唯一
  var newNode = {
  name: name
  };
  if (zTree.getSelectedNodes()[0]) {
  newNode.checked = zTree.getSelectedNodes()[0].checked;
  newNode.pid = zTree.getSelectedNodes()[0].id;
  zTree.addNodes(zTree.getSelectedNodes()[0], newNode);
  } else {
  zTree.addNodes(null, newNode);
  }
  var node = zTree.getNodeByParam("name", name, null); //得到新增加的节点
  zTree.selectNode(node); //选中新增加的节点
  zTree.editName(node); //让新增加的节点处于编辑状态
 }

编辑节点

function editTreeNode() {
  var nodes = zTree.getSelectedNodes(); //得到选中节点集合
  if (nodes && nodes.length > 0) {
  var parent = nodes[0].getParentNode(); //得到选中节点的父节点
  if (parent) {
   nodes[0].pid = parent.id; //如果选中节点父节点存在,将当前结点的pid属性值设置为父节点的id
  }
  zTree.editName(nodes[0]); //让选中节点处于编辑状态
  }
  hideRMenu(); //隐藏右键面板
 };

节点编辑状态离开时触发事件 

//编辑并保存节点
 function beforeRename(treeId, treeNode, newName, isCancel) {
  if (newName.length == 0) { //节点名称判断
  alert("不能为空。");
  return false;
  }
  else {
  $.ajax({   //数据入库
   type: "Post",
   url: "/Design/InsertOrUpdate",
   data: { "dto": { "Id": treeNode.id, "ParentId": treeNode.pid, "Name": newName } },
   succes: function (data) {
   if (data.result == "Faild") {
    layerAlert("保存失败。");
    return false;
   }
   else {
    treeNode.id = data.result; //将返回的id赋值给当前结点
    return true;
   }

   }
  });
  }
 };

删除节点数据 

function removeTreeNode() {
  hideRMenu();
  var nodes = zTree.getSelectedNodes();
  if (nodes && nodes.length > 0) {
  if (nodes[0].children && nodes[0].children.length > 0) {
   alert("包含下级,无法删除。");
  } else {
   if (confirm("该操作会将关联数据同步删除,是否确认删除?") == true) {
   $.ajax({
    type: "Post",
    url: "/Design/Delete",
    data: { "id": nodes[0].id },
    success: function (data) {
    if (data.result == "Success") {
     zTree.removeNode(nodes[0]);
    }
    else {
     alert("删除失败。");
    }
    }
   });
   };
  }
  }
 };

2.4 一些总结
 我们通常使用到树形控件做授权或关联类似的操作,一般会先全部取消勾选,然后根据选中的数据关联对树控件的复选框进行选中操作,在大数据量时,大约几万条数据,全部取消勾选+根据关联数据勾选相关节点这个操作通过js执行会很慢,这种情况建议在后台通过关联关系重新组织zTree需要的数据源,对每条数据(对应树节点)设置checked属性,然后再前台页面重新加载树,这种操作速度要快得多。 

$.ajax({
  type: "Get",
  url: "/Model/GetRelationModelTreeData?designId=" + treeNode.id + "&t=" + new Date(),
  success: function (data) {
  //$.each(data.result, function (i, item) {
  // var node = modelTree.getNodeByParam("id", item, null);
  // modelTree.checkNode(node, true, true);
  //});
  $.fn.zTree.init($("#treejian"), setting1, data.result); //改为重新加载,比js循环勾选速度要快。
  }
 });

更多关于ztree控件的内容,请参考专题《jQuery插件ztree使用汇总》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js改变鼠标的形状和样式的方法
Mar 31 Javascript
JavaScript中的Function函数
Aug 27 Javascript
js实现选中页面文字将其分享到新浪微博
Nov 05 Javascript
跟我学习javascript的函数和函数表达式
Nov 16 Javascript
JS实现HTML表格排序功能
Aug 05 Javascript
又一款js时钟!transform实现时钟效果
Aug 15 Javascript
JS文件上传神器bootstrap fileinput详解
Jan 28 Javascript
javascript中replace使用方法总结
Mar 01 Javascript
Angularjs的启动过程分析
Jul 18 Javascript
Windows下支持自动更新的Electron应用脚手架的方法
Dec 24 Javascript
微信小程序云开发如何使用npm安装依赖
May 18 Javascript
JavaScript的Set数据结构详解
Feb 18 Javascript
jquery 判断selection range 是否在容器中的简单实例
Aug 02 #Javascript
AngularJS基础 ng-model 指令详解及示例代码
Aug 02 #Javascript
JS获取input file绝对路径的方法(推荐)
Aug 02 #Javascript
JavaScript实现复制文章自动添加版权
Aug 02 #Javascript
js获取上传文件的绝对路径实现方法
Aug 02 #Javascript
AngularJS基础 ng-list 指令详解及示例代码
Aug 02 #Javascript
jQuery设置聚焦并使光标位置在文字最后的实现方法
Aug 02 #Javascript
You might like
德生PL660的电路分析和打磨
2021/03/02 无线电
手把手教你使用DedeCms V3的在线采集图文教程
2007/04/03 PHP
解析关于java,php以及html的所有文件编码与乱码的处理方法汇总
2013/06/24 PHP
php防止SQL注入详解及防范
2013/11/12 PHP
smarty内置函数foreach用法实例
2015/01/22 PHP
php短网址和数字之间相互转换的方法
2015/03/13 PHP
php多线程实现方法及用法实例详解
2015/10/26 PHP
PHP自定义函数获取汉字首字母的方法
2016/12/01 PHP
PHP调用全国天气预报数据接口查询天气示例
2019/02/20 PHP
关于JavaScript中string 的replace
2013/04/12 Javascript
Jquery实现列表(隔行换色,全选,鼠标滑过当前行)效果实例
2013/06/09 Javascript
JQuery事件e参数的方法preventDefault()取消默认行为
2013/09/26 Javascript
使用focus方法让光标默认停留在INPUT框
2014/07/29 Javascript
js封装可使用的构造函数继承用法分析
2015/01/28 Javascript
JS实现title标题栏文字不间断滚动显示效果
2016/09/07 Javascript
jQuery插件HighCharts实现的2D回归直线散点效果示例【附demo源码下载】
2017/03/09 Javascript
JavaScript变量作用域_动力节点Java学院整理
2017/06/27 Javascript
js监听html页面的上下滚动事件方法
2018/09/11 Javascript
js实现图片放大并跟随鼠标移动特效
2019/01/18 Javascript
利用百度echarts实现图表功能简单入门示例【附源码下载】
2019/06/10 Javascript
js实现文章目录索引导航(table of content)
2020/05/10 Javascript
Vue单文件组件开发实现过程详解
2020/07/30 Javascript
Python微信公众号开发平台
2018/01/25 Python
Python使用wget实现下载网络文件功能示例
2018/05/31 Python
利用python实现对web服务器的目录探测的方法
2019/02/26 Python
使用python自动追踪你的快递(物流推送邮箱)
2020/03/17 Python
浅谈python opencv对图像颜色通道进行加减操作溢出
2020/06/03 Python
推荐值得学习的12款python-web开发框架
2020/08/10 Python
全方位了解CSS3的Regions扩展
2015/08/07 HTML / CSS
芬兰汽车配件商店:Autonvaraosat24
2017/01/30 全球购物
意大利在线药房:Saninforma
2021/02/11 全球购物
市场营销毕业生自荐信范文
2014/04/01 职场文书
物业管理委托协议(2篇)
2014/09/23 职场文书
缓刑人员思想汇报
2014/10/11 职场文书
django如何自定义manage.py管理命令
2021/04/27 Python
MySQL如何使用使用Xtrabackup进行备份和恢复
2021/06/21 MySQL