jstree 的一些爬坑指南使用说明
需要引用的库
- 官方文档
- css库
<link rel="stylesheet" href="./jstree/dist/themes/default/style.css">
- bootstrap 库 可选
- js库
<script src="https://cdn.bootcss.com/jquery/2.2.3/jquery.js"></script>
<script src="./jstree/dist/jstree.js"></script>
首先使用 jstree
需要 有一个 容器
- 官方使用的容器为
<div id="container"></div>
接下来是 js 将 jstree 实例化
$('#container').jstree({ 'core': { 'data': aa, // 允许执行右键操作 "check_callback": true }, "plugins": ["contextmenu"] }) /* 插件还有这些 按需使用 "plugins" : [ "checkbox", "contextmenu", "dnd", "massload", "search", "sort", "state", "types", "unique", "wholerow", "changed", "conditionalselect" ] */
下面是针对右键功能插件的使用
// 配置文件 $('#container').jstree({ 'core': { 'data': aa, "check_callback": true }, "contextmenu": { "items": { // 需要新建几个就增加几个 "newNode" : newNode, "newChildNode": newChildNode, "removeNode": removeNode // 如果需要继续增加 } } }) var newNode = { "label": "新建本级", "action": function (data) { console.log(data) var inst = $.jstree.reference(data.reference), obj = inst.get_node(data.reference); // 获取父级 var instParent = $.jstree.reference(obj.parent), // 父级内容 objParent = instParent.get_node(obj.parent) // console.log("instParent:", instParent, objParent, obj) // 获取插入的位置 var pos = $(data.reference.prevObject[0]).index() + 1; instParent.create_node(objParent, {}, pos, function (new_node) { console.log("new_node:", new_node) try { new_node.text = "新建文件"; inst.edit(new_node); } catch (ex) { setTimeout(function () { inst.edit(new_node); }, 0); } }); } } var newChildNode = { "label": "新建下级", "action": function (data) { var inst = $.jstree.reference(data.reference), obj = inst.get_node(data.reference); inst.create_node(obj, {}, "last", function (new_node) { try { new_node.text = "新建文件"; inst.edit(new_node); todoId = "#" + new_node.id; } catch (ex) { setTimeout(function () { inst.edit(new_node); }, 0); } }); } } var removeNode = { "label": "删除本节点", "title": "只能删除新建节点", "_disabled": true, "action": function (data) { var inst = $.jstree.reference(data.reference), obj = inst.get_node(data.reference); if (inst.is_selected(obj)) { inst.delete_node(inst.get_selected()); } else { inst.delete_node(obj); } } }
文档中一些 Event 的使用
/** * 创建节点时触发事件 * */ $('#container').on("create_node.jstree", function (e, node) { // 新增是否可删除属性 node.node.li_attr.node_type = "create_node"; node.node.a_attr.node_type = "create_node"; }) /** * 弹出右键菜单时,解析事件 * 在解析contextmenu时触发文档(构建HTML) * @param {dom} data.reference 右键单击的元素 * @param {dom} data.element 菜单本身的DOM元素 * @param {dom} data.positon 菜单的x和y坐标 * */ $(document).on("context_show.vakata", function (e, data) { // data.element 弹出的右键菜单 在 show_contextmenu.jstree 事件之前发生 if (data.reference.attr("node_type") === "create_node") { // vakata-contextmenu-disabled 设置者禁止使用的类名 $(data.element[0].lastChild).removeClass(" vakata-contextmenu-disabled "); } }) /** * 右键菜单显示时的内容 * */ $('#container').on("show_contextmenu.jstree", function (obj, x, y, i) { // 回调 })
外部按钮 创建节点方法
// 创建同级节点 function newNode() { var ref = $('#container').jstree(true), sel = ref.get_selected(true); console.log("sel:true", sel[0]) var refParnet = $.jstree.reference(ref.parent) === null ? "#" : $.jstree.reference(ref.parent) // 获取插入的位置 var pos = $("#" + sel[0].id).index() + 1; if (!sel.length) { return false; } // console.log(ref, sel,refParnet) sel = sel[0].parent; sel = ref.create_node(sel); if (sel) { ref.edit(sel); } }; // 创建子级节点 function newChildNode() { var ref = $('#container').jstree(true), sel = ref.get_selected(); if (!sel.length) { return false; } sel = sel[0]; sel = ref.create_node(sel, { "type": "file" }); if (sel) { ref.edit(sel); } }; // 节点重命名 function demo_rename() { var ref = $('#container').jstree(true), sel = ref.get_selected(); if (!sel.length) { return false; } sel = sel[0]; ref.edit(sel); }; // 节点删除 function removeNode() { var ref = $('#container').jstree(true), sel = ref.get_selected(); if (!sel.length) { return false; } ref.delete_node(sel); };
调用
<div class="button"> <button onclick="newNode()">创建选中同级节点</button> <button onclick="newChildNode()">创建选中子级节点</button> <button onclick="removeNode()">删除节点</button> </div>
一些其他说明
方法 | 说明 |
---|---|
get_selected(param) | param: 可传 true 也可以不传 传 true 返回的数组将包含完整的节点对 不传参 只返回 ID |
$.jstree.reference (needle) | 获取对现有实例的引用 |
multiple | 默认为 true 可以多选 false 禁止多选 |
data.node.original | 传入数据的原数据处理结果 |
$container.jstree()._model.data | 对原数据解析成简单的数据 |
$container.jstree().open_node() | 打开节点,传入的可以是数组,但是其不会打开要打开的节点的父节点 |
$container.jstree()._open_to() | 打开到摸个节点,会打开其父节点,只能打开一个不支持数组 |
ready.jstree | 加载完节点后执行 |
8. 一些提高体验的方法
新建节点时的一些操作
//选中节点的时候打开或关闭节点 $('#container').on('changed.jstree', function (e, data) { console.log("e:",e,data) $('#container').jstree(true).toggle_node(data.selected); }); // 设定 有规则的 ID $container.jstree(true).set_id(node.node,2333333); // 创建节点的是触发 $container.on("create_node.jstree", function (e, node) { // 设定 有规则的 ID $container.jstree(true).set_id(node.node,2333333); // 新增是否可删除属性 node.node.li_attr.node_type = "create_node"; node.node.a_attr.node_type = "create_node"; })
打开全部节点 或者打开全部第几级节点
// 传入的值 打开第几层目录 var level_node = $(this).val(); // 全打开 if (level_node === "open_all") { $container.jstree().open_all(); // 全关闭 } else if (level_node === "close_all") { $container.jstree().close_all(); }else{ // 优化数据在下边 /* // 先关闭所有节点,在对应打开 $container.jstree().close_all(); // 获取数据 迭代数据 并打开 // console.log($container.jstree()._model.data) var levelData = $container.jstree()._model.data; // 打开具体第几级节点 $container.jstree().open_node(aa[0].id, function (e, data) { console.log(e,e.instance, data) }) // 遍历 层级数据的 key 与 value for (var key in levelData) { // 判断 层级数据中的 数据有多少个父层级 当父层级 <= 要打开的层级数目时 则打开该层级 以及其父层级 if (levelData[key].parents.length <= (parseInt(level_node) + 1)) { // console.log("打开了没有打开的节点") $container.jstree()._open_to(key); } } */ /* 对上边的优化 */ $container.jstree().close_all(); // 获取数据 迭代 数据并打开 // console.log($container.jstree()._model.data) var levelData = $container.jstree()._model.data; var keyArry = []; // 需要代开的节点数组 // 遍历 层级数据的 key 与 value for (var key in levelData) { // 判断 层级数据中的 数据有多少个父层级 当父层级 <= 要打开的层级数目时 则打开该层级 以及其父层级 并且数组去重 if (levelData[key].parents.length <= (parseInt(level_node)) && !keyArry.includes(key)) { keyArry.push(key); } } $container.jstree().open_node(keyArry); }
节点加载完成后获取数据
$container.on("load_node.jstree",function (e,data) { // console.log(e,data) var selectOptionNum = 0; for (const key in data.instance._model.data) { // 获取数据 做对比 var maxVle = data.instance._model.data[key].parents.length; selectOptionNum = selectOptionNum < maxVle ? maxVle : selectOptionNum } }) // 或者使用以下方法获取对象数组的最深层级数 以下为es6 写法 // 此方法转自 https://blog.csdn.net/qq_39258914/article/details/81328234 function getMaxFloor (treeData) { let floor = 0 let v = this let max = 0 function each (data, floor) { data.forEach(e => { e.floor = floor if (floor > max) { max = floor } if (e.children.length > 0) { each(e.children, floor + 1) } }) } each(treeData,1) return max }
指定新创建的节点的ID
$container.on("create_node.jstree", function (e, node) { // 设定 有规则的 ID // set_id_name 设定的id值 $container.jstree(true).set_id(node.node,set_id_name); console.log(e,node) // 新增是否可删除属性 node.node.li_attr.node_type = "create_node"; node.node.a_attr.node_type = "create_node"; })