LayUI Tree 组件扩展实现(搜索功能,复选框,自定义节点图标,右击菜单)(附带源码)

本文主要是介绍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: ["&#xe623;", "&#xe625;"],checkbox: ["&#xe626;", "&#xe627;"],radio: ["&#xe62b;", "&#xe62a;"],branch: ["&#xe622;", "&#xe624;"],leaf: "&#xe621;"},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 组件扩展实现(搜索功能,复选框,自定义节点图标,右击菜单)(附带源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/472805

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象