详解js树形控件—zTree使用总结


Posted in Javascript onDecember 28, 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包括以下组成部分

详解js树形控件—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>

运行结果如下

详解js树形控件—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>

详解js树形控件—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 } },
     success: 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循环勾选速度要快。
   }
  });

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

Javascript 相关文章推荐
JavaScript触发器详解
Mar 10 Javascript
jquery Moblie入门—hello world的示例代码学习
Jan 08 Javascript
javascript里模拟sleep(两种实现方式)
Jan 25 Javascript
JavaScript正则表达式之multiline属性的应用
Jun 16 Javascript
jQuery 常用代码集锦(必看篇)
May 16 Javascript
Node.js的文件权限及读写flag详解
Oct 11 Javascript
微信小程序 跳转传参数与传对象详解及实例代码
Mar 14 Javascript
javascript实现多张图片左右无缝滚动效果
Mar 22 Javascript
原生JS实现圆环拖拽效果
Apr 07 Javascript
微信小程序如何像vue一样在动态绑定类名
Apr 17 Javascript
layui前端框架之table表数据的刷新方法
Aug 17 Javascript
在Vant的基础上封装下拉日期控件的代码示例
Dec 05 Javascript
js 轮播效果实例分享
Dec 28 #Javascript
JS正则RegExp.test()使用注意事项(不具有重复性)
Dec 28 #Javascript
Bootstrap 模态框实例插件案例分析
Dec 28 #Javascript
Angular使用ng-messages与PHP进行表单数据验证
Dec 28 #Javascript
Bootstrap中datetimepicker使用小结
Dec 28 #Javascript
html5+CSS 实现禁止IOS长按复制粘贴功能
Dec 28 #Javascript
angular-ui-sortable实现可拖拽排序列表
Dec 28 #Javascript
You might like
windows server 2008/2012安装php iis7 mysql环境搭建教程
2016/06/30 PHP
PHP有序表查找之二分查找(折半查找)算法示例
2018/02/09 PHP
PHP 文件写入和读取操作实例详解【必看篇】
2019/11/04 PHP
如何判断图片地址是否失效
2007/02/02 Javascript
HTML中Select不用Disabled实现ReadOnly的效果
2008/04/07 Javascript
javascript 解决表单仍然提交即使监听处理函数返回false
2010/03/14 Javascript
JQuery中如何传递参数如click(),change()等具体实现
2013/04/28 Javascript
5秒后跳转到另一个页面的js代码
2013/10/12 Javascript
javascript中scrollTop详解
2015/04/13 Javascript
JavaScript实现弹出DIV层同时页面背景渐变成半透明效果
2016/03/25 Javascript
Jquery实现$.fn.extend和$.extend函数
2016/04/14 Javascript
JavaScript日期对象(Date)基本用法示例
2017/01/18 Javascript
JavaScript中立即执行函数实例详解
2017/11/04 Javascript
JS获取浏览器地址栏的多个参数值的任意值实例代码
2018/07/24 Javascript
详解如何写出一个利于扩展的vue路由配置
2019/05/16 Javascript
微信小程序左滑删除实现代码实例
2019/09/16 Javascript
vue + elementUI实现省市县三级联动的方法示例
2019/10/29 Javascript
JavaScript实现多层颜色选项卡嵌套
2020/09/21 Javascript
[11:27]《一刀刀一天》之DOTA全时刻20:TI4总奖金突破920W TS赛事分析
2014/06/18 DOTA
玩转python爬虫之cookie使用方法
2016/02/17 Python
python shell根据ip获取主机名代码示例
2017/11/25 Python
浅谈Django自定义模板标签template_tags的用处
2017/12/20 Python
python3.x 将byte转成字符串的方法
2018/07/17 Python
简单了解python的一些位运算技巧
2019/07/13 Python
Python提取PDF内容的方法(文本、图像、线条等)
2019/09/25 Python
使用apiDoc实现python接口文档编写
2019/11/19 Python
Python PIL库图片灰化处理
2020/04/07 Python
使用CSS3制作倾斜导航条和毛玻璃效果
2017/09/12 HTML / CSS
C语言开发工程师测试题
2016/12/20 面试题
新护士岗前培训制度
2014/02/02 职场文书
介绍信的写法
2015/01/31 职场文书
启迪人心的励志语录:脾气永远不要大于本事
2020/01/02 职场文书
Nginx中break与last的区别详析
2021/03/31 Servers
Windows下redis下载、redis安装及使用教程
2021/06/02 Redis
高性能跳频抗干扰宽带自组网电台
2022/02/18 无线电
zabbix配置nginx监控的实现
2022/05/25 Servers