本文主要是介绍LayUI Tree 组件扩展实现(搜索功能,复选框,自定义节点图标,右击菜单)(附带源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近项目选项前端技术选型选择了LayUI,没选到的是tree组件的功能实在太弱了,没办了,只能自己修改了源码,目前实现了以下功能,github还没有时间更新敬请期待。那我们来看看扩展功能吧:
一、扩展功能
1,增加了目录树的搜索功能
2,增加了目录树的复选框和事件回调的实现
3,增加了根节点图标和叶子图标自定义设置。
4,增加右键菜单和事件回调。
让我妈看一下效果图吧
二、让我看一下实现源码吧
调用方式
layui.use(['tree', 'layer'], function () {var layer = layui.layer, $ = layui.jquery, tree = layui.tree;// 同步(绑定)layui的tree的搜索(过滤)框// treeId: tree所在的容器的id// filter: 对应的搜索框的selector或者dom对象,尽量要确保是唯一的节点,或者真的是要控制这个树的input// callback: 回调 参数(树节点jquery对象, 输入框对象, 匹配到的节点数量)tree.syncLayuiTreeFilter = function (treeId, filter, callback) {var treeElem = $('#' + treeId), filterElem = $(filter);if (!filterElem.length || !filterElem.length) {return;}filterElem.keyup(function (event) {var that = this;var value = $(that).val().trim().toLocaleLowerCase();//不区分大小写var HIDE = 'layui-hide';var hintClass = 'search_hit';// 先恢复现场treeElem.find('.' + HIDE).removeClass(HIDE);treeElem.find('.' + hintClass).removeClass(hintClass).each(function (index, item) {item = $(item);item.html(item.data('textOld')).data('textOld', null);});// 如果有值筛选开始if (value) {layui.each(treeElem.find('cite'), function (index, elem) {elem = $(elem);var textTemp = elem.text();if (textTemp.toLocaleLowerCase().indexOf(value) === -1) { //不区分大小写// 不存在就隐藏elem.closest('li').addClass(HIDE);} else {// 命中就添加一个classelem.addClass(hintClass).data('textOld', textTemp).html(textTemp.replace(new RegExp(value, 'g'), '<span class="search_hint_text">' + value + '</span>'));}});layui.each(treeElem.find('.' + hintClass), function (index, elem) {elem = $(elem);elem.parents('li').removeClass(HIDE);elem.parents('ul').each(function (i, item) {if (!$(item).hasClass('layui-show')) {$(item).parent('li').find('>i').click();}});elem.parents('ul').parent('li').removeClass(HIDE);});}typeof callback === 'function' && callback.call(that, treeElem, filterElem, treeElem.find('.' + hintClass).length);});};tree({elem: '#layTree' //指定元素,branchExtent:["Ico_fold","Ico_launch"] //树形折叠图标第一个是折叠样式,第二个展开样式,target: '_blank' //是否新选项卡打开(比如节点返回href才有效),check: 'checkbox',checkboxName: 'ck'//复选框的name属性值,checkboxStyle: "",drag: true, nodes: [ //节点{name: '常用文件夹',id: 1,alias: 'changyong',checked: true,data:{text:123,//data-text 用于存储数据ceshi:456}, children: [{name: '所有未读', id: 11, href: 'http://www.layui.com/', alias: 'weidu', checked: true,leaf:"Ico_point1" //css样式,data:{}},{name: '置顶邮件',id: 12,leaf:"Ico_point2",data:{}}, {name: '邮件标签邮件',id: 13,leaf:"Ico_point3",data:{},children: [{name: '所有未读', id: 11, href: 'http://www.layui.com/', alias: 'weidu', checked: true, leaf:"Ico_point1" //css样式,data:{}},{name: '置顶邮件',id: 12,leaf:"Ico_point2",data:{}}, {name: '邮件标签邮件',id: 13,leaf:"Ico_point3",data:{}}]}]}],click: function(node){console.log(node) //node即为当前点击的节点数据var as= $("#layTree").find('a');$.each(as,function (index,obj) {if($(obj).children("cite").text()=='置顶邮件') {console.log($(obj).parent());$(obj).parent().append("<ul class=\"layui-show\"><li><i style=\"paddling-left: 28px;\"></i><input type=\"checkbox\" name=\"ck\" checked=\"checked\" data-parent-id=\"lyn_1554703113157_1_3_lel\" id=\"lyn_1554703113158_3_5_nly\"><a href=\"http://www.layui.com/\" target=\"_blank\"><i class=\"layui-icon Ico_point1\"></i><cite>所有未读</cite></a></li><li><i style=\"paddling-left: 28px;\"></i><input type=\"checkbox\" name=\"ck\" data-parent-id=\"lyn_1554703113157_1_3_lel\" id=\"lyn_1554703113160_5_7_nayryl\"><a href=\"javascript:;\" class=\"\"><i class=\"layui-icon Ico_point2\"></i><cite>置顶邮件</cite></a></li><li><i class=\"layui-icon layui-tree-spread\"></i><input type=\"checkbox\" name=\"ck\" data-parent-id=\"lyn_1554703113157_1_3_lel\" id=\"lyn_1554703113160_7_9_ney\"><a href=\"javascript:;\"><i class=\"layui-icon Ico_fold\"></i><cite>邮件标签邮件</cite></a><ul class=\"\"><li><i style=\"paddling-left: 28px;\"></i><input type=\"checkbox\" name=\"ck\" checked=\"checked\" data-parent-id=\"lyn_1554703113160_7_9_ney\" id=\"lyn_1554703113161_9_11_aa\"><a href=\"http://www.layui.com/\" target=\"_blank\"><i class=\"layui-icon Ico_point1\"></i><cite>所有未读</cite></a></li><li><i style=\"paddling-left: 28px;\"></i><input type=\"checkbox\" name=\"ck\" data-parent-id=\"lyn_1554703113160_7_9_ney\" id=\"lyn_1554703113161_11_13_lrl\"><a href=\"javascript:;\"><i class=\"layui-icon Ico_point2\"></i><cite>置顶邮件</cite></a></li><li><i style=\"paddling-left: 28px;\"></i><input type=\"checkbox\" name=\"ck\" data-parent-id=\"lyn_1554703113160_7_9_ney\" id=\"lyn_1554703113162_13_15_e\"><a href=\"javascript:;\"><i class=\"layui-icon Ico_point3\"></i><cite>邮件标签邮件</cite></a></li></ul></li></ul>");//element.init();// tree.render();return false;}})},onchange: function (event,item){//当当前input发生变化后所执行的回调console.log(item); //item即为当前点击的节点数据console.log(event); //事件源},rightClick:function(event,elem) {console.log("你的鼠标右击了我!"+elem);console.log(elem);event.preventDefault();return false;}});tree.syncLayuiTreeFilter('layTree', '[name="searchTree"]', function (treeElem, filterElem, hitNumbers) {console.log('hitNumbers', hitNumbers);layer.msg('找到' + hitNumbers + '个节点');});
tree.js 源码
//扩展日志 author:wangxianyang
//1,增加复选框并且加上了事件回调和参数传递
//2,增加了折叠图标和叶子图标的自定义扩展
//3,增加了右击菜单事件和参数传递
//4,增加了tree的搜索功能(模糊匹配不区分大小写)
;
layui.define("jquery",function(e) {"use strict";var o = layui.jquery,a = layui.hint(),r = "layui-tree-enter",i = function(e) {this.options = e},t = {arrow: ["", ""],checkbox: ["", ""],radio: ["", ""],branch: ["", ""],leaf: ""},branchExtent,//折叠图标扩展leafExtent="",//叶子图标扩展leftClick=true,num = 1;i.prototype.init = function(e) {var o = this;branchExtent=o.options.branchExtent||["",""];e.addClass("layui-box layui-tree"),o.options.skin && e.addClass("layui-tree-skin-" + o.options.skin),o.tree(e),o.on(e)//e.preventDefault();false;},i.prototype.tree = function(e, a) {var r = this,i = r.options,n = a || i.nodes;layui.each(n,function(a, n) {var id = r.uuid();n.id = id;//console.log(n.data);if (n.children) {layui.each(n.children,function(index, item) {item.pid = n.id;});}var l = n.children && n.children.length > 0,c = o('<ul class="' + (n.spread ? "layui-show": "") + '"></ul>'),s = o(["<li " + (n.spread ? 'data-spread="' + n.spread + '"': "") + ">",function() {return l ? '<i class="layui-icon layui-tree-spread">' + (n.spread ? t.arrow[1] : t.arrow[0]) + '</i>': '<i style="paddling-left: 28px;"></i>';} (),function() {var eleStr = i.check && i.check == "checkbox" ? '<input type="checkbox" name="' + i.checkboxName + '" ' + ((n.checked && n.checked == true) ? 'checked="checked"': "") + (n.checkboxValue ? ('value="' + n.checkboxValue + '"') : "") + 'data-parent-id="' + n.pid + '"' + 'id="' + n.id + '"' + (i.checkboxStyle ? (' style="' + i.checkboxStyle + '"') : "") : '';if (eleStr.length > 0) {if (n.data && Object.prototype.toString.call(n.data) == "[object Object]") {for (var attr in n.data) {eleStr += ' data-' + attr + '=' + n.data[attr];}}eleStr += ' />';}return eleStr;} (),function() {//debugger;//return '<a href="' + (n.href || "javascript:;") + '" ' + (i.target && n.href ? 'target="' + i.target + '"': "") + ">" + ('<i class="layui-icon layui-tree-' + (l ? "branch": "leaf") + '">' + (l ? n.spread ? t.branch[1] : t.branch[0] : t.leaf) + "</i>") + ("<cite>" + (n.name || "未命名") + "</cite></a>")return '<a href="' + (n.href || "javascript:;") + '" '+ (i.target && n.href ? 'target="' + i.target + '"': "") + ">"+ ('<i class="layui-icon ' + (l ? n.spread ? branchExtent[1] : branchExtent[0] : n.leaf) + '">'+ "</i>") + ("<cite>" + (n.name || "未命名") + "</cite></a>")} (), "</li>"].join(""));l && (s.append(c), r.tree(c, n.children)),e.append(s), "function" == typeof i.click && r.click(s, n),r.spread(s, n), i.drag && r.drag(s, n) , i.onchange && r.changed(s, n) //注册复选框事件})},i.prototype.changed = function(e, o) {var r = this;if (o.pid == undefined || o.pid == null) {e.children("input").on("change",function() {var childUl = e.children("ul"),checked = this.checked;childUl.find("input").prop("checked", checked);try {// debugger;r.options.onchange((e.children("input").prop("checked") || false), o);} catch(e) {}});} else {e.children("input").on("change",function() {var that = this;if (!this.checked) {childCheckboxCheckOrNot.call(this);r.cancelParentsCheckboxCheck(that);} else {r.parentsChecked(this, this.checked);childCheckboxCheckOrNot.call(this);}try {//debugger;r.options.onchange((e.children("input").prop("checked") || false), o);} catch(e) {}});}function childCheckboxCheckOrNot() {if (o.children && o.children.length > 0) {var childUl = e.children("ul"),checked = this.checked;childUl.find("input").prop("checked", checked);}}},i.prototype.cancelParentsCheckboxCheck = function(ele) {if (!ele) {return;}var r = this,siblingInputs = r.siblingInputs(ele),parentId = ele.getAttribute("data-parent-id"),parentInput = null,bool = true,childrendInputs = null,hasOneChildrenInputCheck = false;if (parentId != 'undefined') {parentInput = document.getElementById(parentId);childrendInputs = r.currentChildrenInputs(parentInput);}for (var i = 0,len = siblingInputs.length; i < len; i++) {if (siblingInputs[i].checked) {bool = false;break;}}if (!childrendInputs || childrendInputs.length == 0) {hasOneChildrenInputCheck = false;} else {for (var j = 0,len2 = childrendInputs.length; j < len2; j++) {if (childrendInputs[j].getAttribute("data-parent-id") != "undefined") {if (childrendInputs[j].checked) {hasOneChildrenInputCheck = true;break;}}}}if (bool && !hasOneChildrenInputCheck) {r.inputChecked(parentInput, false);}this.cancelParentsCheckboxCheck(parentInput);},i.prototype.siblingInputs = function(ele) {var that = this;if (ele) {var parent = ele.parentElement,parents = parent.parentElement,childrens = parents.children,siblingInputs = [];} else {return null;}for (var i = 0,len = childrens.length; i < len; i++) {if (childrens[i] != parent) {if (childrens[i].children[0].nodeName == "INPUT") {siblingInputs.push(childrens[i].children[0]);}if (childrens[i].children[1].nodeName == "INPUT") {siblingInputs.push(childrens[i].children[1]);}}}parent = null;parents = null;childrens = null;return siblingInputs;},i.prototype.currentChildrenInputs = function(ele) {var parent = ele.parentElement,childrenInputs = [];if (parent.getElementsByTagName("ul").length > 0) {var uls = parent.getElementsByTagName("ul");for (var i = 0,len = uls.length; i < len; i++) {var inputs = uls[i].getElementsByTagName("input");for (var j = 0,len2 = inputs.length; j < len2; j++) {childrenInputs.push(inputs[j]);}}}return childrenInputs;},i.prototype.inputChecked = function(ele, checked) {ele && (ele.checked = checked);},i.prototype.parentsChecked = function(e, checked) {var r = this,i = r.options,selector = i.elem,currentInput = e;if (currentInput && (currentInput.nodeName == "INPUT")) {var parentId = currentInput.getAttribute("data-parent-id"),parentInput = null;setTimeout(function() {r.inputChecked(currentInput, checked);if (parentId) {r.parentsChecked(document.getElementById(parentId), checked);}},50);}},i.prototype.findParents = function(ele, selector) {var parent = ele.parentElement,that = this;if (selector.substr(0, 1) == "#") {if (parent) {if (parent.id != selector.substr(1)) {that.findParents(parent, selector);} else {return parent;}}} else if (selector.substr(0, 1) == ".") {if (parent) {var classnameArr = parent.className.split(" "),len = classnameArr.length,selectt = selector.substr(1),hasSelector = false;if (len > 0) {for (var i = 0; i < len; i++) {if (classnameArr[i] == selectt) {hasSelector = true;break;}}}if (!hasSelector) {that.findParents(parent, selector);} else if (hasSelector) {return parent;}}}},i.prototype.uuid = function() {var that = this,randomStr = ['l', 'a', 'y', 'e', 'r', 'n', 'i'],randomNum = Math.floor(Math.random() * 6);return function() {var str = "";for (var i = 0; i <= randomNum; i++) {str += randomStr[Math.floor(Math.random() * 6)];}return "lyn_" + new Date().getTime() + "_" + (num++) + "_" + (++num) + "_" + str;} ();},i.prototype.click = function(e, o) {var a = this,r = a.options;e.children("a").on("click",function(e) {//debugger;layui.stope(e),r.click(o)})},i.prototype.spread = function(e, o) {//debugger;var a = this,r = (a.options, e.children(".layui-tree-spread")),i = e.children("ul"),n = e.children("a"),l = function() {e.data("spread") ? (e.data("spread", null), i.removeClass("layui-show"), r.html(t.arrow[0]),n.find(".layui-icon").removeClass(branchExtent[1]).addClass(branchExtent[0])) : (e.data("spread", !0), i.addClass("layui-show"), r.html(t.arrow[1]), n.find(".layui-icon").removeClass(branchExtent[0]).addClass(branchExtent[1]))};i[0] && (r.on("click", l), n.on("dblclick", l))},//n.find(".layui-icon").html(t.branchExtent[0])):(e.data("spread",!0),i.addClass("layui-show"),r.html(t.arrow[1]),//n.find(".layui-icon").html(t.branchExtent[1]))};i[0]&&(r.on("click",l),n.on("dblclick",l))},i.prototype.on = function(e) {var a = this,i = a.options,t = "layui-tree-drag";e.find("i").on("selectstart",function(e) {return ! 1}),i.drag && o(document).on("mousemove",function(e) {var r = a.move;if (r.from) {var i = (r.to, o('<div class="layui-box ' + t + '"></div>'));e.preventDefault(),o("." + t)[0] || o("body").append(i);var n = o("." + t)[0] ? o("." + t) : i;n.addClass("layui-show").html(r.from.elem.children("a").html()),n.css({left: e.pageX + 10,top: e.pageY + 10})}}).on("mouseup",function(ev) {var ee = a.move;if(ee.from && ee.from.elem && ee.from.elem[0]){//自定义鼠标右击事件//debugger;ee.from.elem[0].oncontextmenu = function(){//debugger;if(!leftClick){leftClick=true;}if(typeof i.rightClick=="function" ){var oEvent=ev.event;if (!oEvent) oEvent=window.event;if (oEvent.button==2) {try { //debugger;leftClick=!leftClick;if(!leftClick){layui.stope(e);i.rightClick(a,ee);//leftClick=false;}} catch(e) {}oEvent.stopPropagation();oEvent.preventDefault();return false;}}}}ee.from && (ee.from.elem.children("a").removeClass(r), ee.to && ee.to.elem.children("a").removeClass(r), a.move = {},o("." + t).remove());ev.preventDefault();return false;})},i.prototype.move = {},i.prototype.drag = function(e, a) {var i = this,t = (i.options, e.children("a")),n = function() {var t = o(this),n = i.move;n.from && (n.to = {item: a,elem: e},t.addClass(r))};t.on("mousedown",function() {var o = i.move;o.from = {item: a,elem: e}}),t.on("mouseenter", n).on("mousemove", n).on("mouseleave",function() {var e = o(this),a = i.move;a.from && (delete a.to, e.removeClass(r))})},e("tree",function(e) {var r = new i(e = e || {}),t = o(e.elem);return t[0] ? void r.init(t) : a.error("layui.tree 没有找到" + e.elem + "元素");})})
三、更多
如果你还需要交流问题,
如果你还有不了解的地方,
如果你需要.NET版本构建tree的后台代码,
如果你需要JAVA版本构建tree的后台代码,
一起学习探讨吧。........
可以加入我们的基地,我们基地的地址是:450342630(QQ群号)
这篇关于LayUI Tree 组件扩展实现(搜索功能,复选框,自定义节点图标,右击菜单)(附带源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!