最近在写一个商品分类管理的功能,本来想用layui的树形组件来写,但发现layui原生的tree只能展示title,而分类的其他字段无法展示,这就有点不适用了,无意中看到一位大神自定义写的一个树形表格组件,正好满足我的要求,特此将使用方法以及其中遇到的一些坑记录下来。。。

首先看下treeTable的

 ​演示地址​

 ​项目地址​

好了,如果看完演示到这里你觉得正好符合你的功能要求,就可以继续往下看了,

虽然项目地址中已经把使用介绍的很详细了,但是我在这里要补充一下我遇到的坑:

使用方法

1,引入模块

打开项目地址,将整个项目下载下来,项目中其他文件可以参考,我们主要用的就是treetable-lay这个文件夹的内容。

24100511_61ee0957edd9837568

下载好项目后把treetable-lay放在我们自己项目的任意位置,但是尽量和layui文件夹放一块,好找!

下面是我放的位置,如图所示:

24100512_61ee09584538d78848

2,初始化模块配置

要扩展layui的模块使用我们引入的js模块,注意base路径是treetable-lay文件夹所在的父路径,这里出错会报404,extend内容最好不要改。

下面我先每个重点注意事项单独列出来,最后放完整代码。

layui.config({
base: ‘${pageContext.request.contextPath}/layuiadmin/modules/’ // 资源所在路径
}).extend({
treetable: ‘treetable-lay/treetable’
}).use([‘treetable’, ‘table’, ‘layer’], function () {
var treetable = layui.treetable;
var layer = layui.layer;
var table = layui.table;
var $ = layui.jquery;
});

如下图所示:

24100512_61ee09588742c24944

3,动态渲染表格

数据是从后台查询出来,数据格式不需要做处理,只需要查询所有就行了,官方文档给了json格式,我自己也做了一个简单的封装,一会儿再说json格式。

这里要注意的是treeIdName和treePidName这两个属性,要对应自己查询出来的id和pid。支持自定义这点非常好

<%–树形表格–%>
<table class=”layui-table” id=”Lay_category_treeTable” lay-filter=”Lay_category_treeTable”></table>

//js如下:
layui.use([‘treetable’, ‘table’, ‘layer’], function () {
var treetable = layui.treetable;
var layer = layui.layer;
var table = layui.table;
var $ = layui.jquery;

var re;
// 渲染表格
var renderTable = function () {
layer.load(3); //这里好像是要加载几层 ,我的是3层,就写了个3,
re = treetable.render({
elem: ‘#Lay_category_treeTable’,
url: ‘${basepath}/goodscategory/selectTreeTable’,
treeColIndex: 1, // 树形图标显示在第几列
treeSpid: 0, // 最上级的父级id
treeIdName: ‘classId’, // id字段的名称
treePidName: ‘parentId’, // pid字段的名称
treeDefaultClose: true, //是否默认折叠
page: false,
//treeLinkage: true, //父级展开时是否自动展开所有子级
cols: [[
{type: ‘numbers’},
{title: “分类名称”, field: “className”,align:”left”},
{title: “分类编码”, field: “classCode”},
// {title: “分类层级”, field: “classIdLevel”},
{title: “分类状态”, field: “classIdStatus”,templet: ‘#classIdStatusTpl’},
{title: “创建人”, field: “createUser”},
{
title: “创建时间”,
field: “createTime”,
templet: ‘<div>{{# if(d.createTime!=null){ }} {{ layui.util.toDateString(d.createTime,\’yyyy-MM-dd HH:mm:ss\’) }} {{# } }}</div>’
},
{title: “更新人员”, field: “updateUser”},
{
title: “更新时间”,
field: “updateTime”,
templet: ‘<div>{{# if(d.updateTime!=null){ }} {{ layui.util.toDateString(d.updateTime,\’yyyy-MM-dd HH:mm:ss\’) }} {{# } }}</div>’
},
{title: “操作”, templet: “#updateAndDelete”}
]],
done: function () {
layer.closeAll(‘loading’);
}
})
};


可以使用url传递数据,也可以使用data传递数据,如果使用url传递数据,参数是where字段,

跟layui数据表格的使用方式一致。

4,参数说明,(这里直接复制官方的)

layui数据表格的所有参数都可以用,除此之外treetable新增的参数有:

参数 类型 是否必填 描述
treeColIndex int 树形图标显示在第几列
treeSpid object 最上级的父级id
treeIdName string id字段的名称
treePidName string pid字段的名称
treeDefaultClose boolean 是否默认折叠
treeLinkage boolean 父级展开时是否自动展开所有子级

treeColIndex

树形图标(箭头和文件夹、文件的图标)显示在第几列, 索引值是cols数组的下标。

treeSpid

最上级的父级id,比如你可以规定pid为0或-1的是最顶级的目录。

treeIdName

treetable是以id和pid字段来渲染树形结构的,如果你的数据没有id和pid字段,你可以指定id和pid字段的名称。

treePidName

pid在你的数据字段中的名称。

treeDefaultClose

默认是全部展开的,如果需要默认全部关闭,加上treeDefaultClose:true即可。

treeLinkage

父级展开时是否自动展开所有子级

注意事项

  • 不能使用分页功能,即使写了page:true,也会忽略该参数。
  • 不能使用排序功能,不要开启排序功能。
  • table.reload()不能实现刷新,请参考demo的刷新。
  • 除了文档上写的treetable.xxx的方法之外,其他数据表格的方法都使用table.xxx。
  • 建议删除和修改请求完后台之后请刷新(重新渲染)表格,最好不要使用obj.delete方式删除。

5,其他方法

这里除了layui的方法新增的方法有展开所有,折叠所有,刷新表格 ,三种方法,使用方法如下:

<div class=”layui-btn-group”>
<button class=”layui-btn” id=”btn-expand”>全部展开</button>
<button class=”layui-btn” id=”btn-fold”>全部折叠</button>
<button class=”layui-btn” id=”btn-refresh”>刷新表格</button>
</div>

renderTable(); //这个就是上面的渲染表格 var renderTable = function () {…}
//展开所有
$(‘#btn-expand’).click(function () {
//alert(0)
treetable.expandAll(‘#Lay_category_treeTable’);
});
//折叠所有
$(‘#btn-fold’).click(function () {
// alert(1)
treetable.foldAll(‘#Lay_category_treeTable’);
});
//刷新表格
$(‘#btn-refresh’).click(function () {
renderTable();
});

    
    

    6,content图标。

    图标这个从gitee码云的源码上看吧,不再详细说,也没啥可说的。

    7,我遇到的坑

    我照着他给的教程一步步弄下来页面也显示出来了,但就是不能折叠,不管是我用折叠方法还是点那个三角图片还是设置为默认折叠,就是不管用,

    不能折叠,可把我给气坏了。

    苦思冥想找不到问题,最后我去研究treetable.js这个文件

    发现其中有一段代码他给注释掉了,如下图所示:

    24100512_61ee0958b58e15726

    然后我把注释的这一段代码打开,哎,好了,展开折叠正常了,不知道什么原因,不知道有没有其他人遇到过。。。

    最后,分享一下我写的不成熟的这个页面的功能汇总,做个记录:

    主要功能有,树形表格展示,添加,修改,删除,批量删除,搜索,layui时间日期自定义格式列,表格全部展开、折叠、刷新表格等功能,有兴趣的看下吧~~

    效果图如下所示:

    24100513_61ee0959134b734904

    全部代码在这~:

    <%–
    Created by IntelliJ IDEA.
    User: Administrator
    Date: 2019/9/23
    Time: 13:25
    To change this template use File | Settings | File Templates.
    –%>

    <%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>
    <%@ include file=”../meta.jsp” %>
    <html>
    <head>
    <title>商品分类管理</title>
    <link rel=”stylesheet” href=”${basepath}layuiadmin/layui/css/layui.css” media=”all”>
    <link rel=”stylesheet” href=”${basepath}layuiadmin/modules/treetable-lay/treetable.css”>
    <script type=”text/javascript” src=”${basepath}js/jquery-1.12.0.min.js”></script>
    <script type=”text/javascript” src=”${basepath}js/cookies.js”></script>
    <script type=”text/javascript” src=”${basepath}layuiadmin/layui/layui.js”></script>
    <script type=”text/javascript” src=”${basepath}layuiadmin/modules/treetable-lay/treetable.js”></script>
    <style type=”text/css”>
    .layui-table-cell {
    height: auto;
    line-height: 30px;
    }

    </style>

    </head>
    <body>
    <div class=”layui-card-body”>
    <div style=”padding-bottom: 10px;” id=”LAY_lay_add”>
    <button type=”button” class=”layui-btn layui-btn-danger” onclick=”doMultiDelete()”>
    <i class=”layui-icon layui-icon-delete”></i> 批量删除
    </button>
    <button class=”layui-btn layuiadmin-btn-role ” data-type=”add” onclick=”toOpenAddLayer()”>
    <i class=”layui-icon layui-icon-add-circle-fine”></i> 添加
    </button>
    &nbsp;
    <div class=”layui-input-inline” style=”width: 200px;”>
    <input type=”text” name=”search” id=”Lay_toSearch_input” placeholder=”请输入分类名称” autocomplete=”off”
    class=”layui-input”>
    </div>
    <div class=”layui-input-inline” style=”width: 100px;”>
    <button type=”button” class=”layui-btn layui-btn-normal” id=”btn-search”<%– onclick=”doSearch()”–%>>
    <i class=”layui-icon layui-icon-search”></i> 搜索
    </button>
    </div>
    &nbsp;
    <div class=”layui-btn-group”>
    <button class=”layui-btn” id=”btn-expand”>全部展开</button>
    <button class=”layui-btn” id=”btn-fold”>全部折叠</button>
    <button class=”layui-btn” id=”btn-refresh”>刷新表格</button>
    </div>
    <%–
    <button type=”button” class=”layui-btn layui-btn-normal change-icon”>随机更换小图标</button>
    –%>
    </div>

    <%–树形表格–%>
    <table class=”layui-table” id=”Lay_category_treeTable” lay-filter=”Lay_category_treeTable”></table>

    <%–树形菜单–%>
    <div id=”Lay_category_tree” lay-filter=”Lay_category_tree”></div>

    <%–Table表格–%>
    <%– <table id=”Lay_back_table” lay-filter=”Lay_back_table”></table>–%>

    </div>

    <script type=”text/html” id=”updateAndDelete”>
    <button type=”button” class=”layui-btn layui-btn-normal” onclick=”toOpenUpdateLayer(‘{{d.classId}}’)”>
    <i class=”layui-icon layui-icon-edit”></i>修改
    </button>
    <button type=”button” class=”layui-btn layui-btn-danger” onclick=”doDelete(‘{{d.classId}}’)”>
    <i class=”layui-icon layui-icon-delete”></i> 删除
    </button>
    </script>

    <%–弹出层–%>

    <form id=”addForm” class=”layui-form”>
    <div class=”layui-form” lay-filter=”layuiconfig-form-role” id=”layuiconfig-form-role”
    style=”padding: 20px 30px 0 0;display: none”>
    <div class=”layui-form-item”>
    <label class=”layui-form-label”>分类名称</label>
    <div class=”layui-input-block”>
    <input name=”className” id=”className” class=”layui-input”>
    <input name=”classId” id=”classId” lay-type=”hide” type=”hidden” class=”layui-input”>
    </div>
    </div>
    <div class=”layui-form-item”>
    <label class=”layui-form-label”>分类编码</label>
    <div class=”layui-input-block”>
    <input name=”classCode” id=”classCode” class=”layui-input”>
    </div>
    </div>
    <div class=”layui-form-item”>
    <label class=”layui-form-label”>分类状态</label>
    <div class=”layui-input-block”>
    <input type=”checkbox” lay-skin=”switch” lay-text=”启用|禁用” value=”1″ checked name=”classIdStatus”
    id=”classIdStatus” class=”layui-input”>
    </div>
    </div>

    <div class=”layui-form-item” id=”Lay_select_Level”>
    <label class=”layui-form-label”>请选择分类级别</label>
    <div class=”layui-input-block”>
    <select name=”classIdLevel” lay-verify=”required” lay-filter=”classIdLevel”>
    <option value=””></option>
    <option value=”1″ selected>一级分类</option>
    <option value=”2″>二级分类</option>
    <option value=”3″>三级分类</option>
    </select>
    </div>
    </div>

    <div class=”layui-form-item” style=”display: none” id=”Lay_One_Level”>
    <label class=”layui-form-label”>请选择所属的一级分类</label>
    <div class=”layui-input-block”>
    <select name=”parentId” id=”parentId” lay-filter=”parent_classIdLevel_One”>
    <option value=””></option>
    </select>
    </div>
    </div>

    <div class=”layui-form-item” style=”display: none” id=”Lay_Two_Level” >
    <label class=”layui-form-label”>请选择所属的二级分类</label>
    <div class=”layui-input-block”>
    <select name=”parentId2″ id=”Two_parentId” lay-filter=”parent_classIdLevel_Two”>
    <option value=””></option>
    </select>
    </div>
    </div>

    <div class=”layui-form-item” style=”text-align: right”>
    <button class=”layui-btn ” lay-submit lay-filter=”LAY-sysconfig-submit” id=”LAY-sysconfig-submit”>确认添加
    </button>
    <button lay-submit lay-filter=”updateSubmitBtn” class=”layui-btn” id=”updateSubmitBtn”>确认修改</button>

    </div>
    </div>
    </form>

    <script type=”text/html” id=”classIdStatusTpl”>
    {{# if(d.classIdStatus==1){ }}
    启用
    {{# } else { }}
    <i style=”color: red;”>禁用</i>
    {{# } }}
    </script>

    <script type=”text/javascript”>

    layui.config({
    base: ‘${pageContext.request.contextPath}/layuiadmin/modules/’ // 资源所在路径
    }).extend({
    treetable: ‘treetable-lay/treetable’
    }).use([‘treetable’, ‘table’, ‘layer’], function () {
    var treetable = layui.treetable;
    var layer = layui.layer;
    var table = layui.table;
    var $ = layui.jquery;

    var re;

    // 渲染表格
    var renderTable = function () {
    layer.load(3);
    re = treetable.render({
    elem: ‘#Lay_category_treeTable’,
    url: ‘${basepath}/goodscategory/selectTreeTable’,
    treeColIndex: 1, // 树形图标显示在第几列
    treeSpid: 0, // 最上级的父级id
    treeIdName: ‘classId’, // id字段的名称
    treePidName: ‘parentId’, // pid字段的名称
    treeDefaultClose: true, //是否默认折叠
    page: false,
    //treeLinkage: true, //父级展开时是否自动展开所有子级
    cols: [[
    {type: ‘numbers’},
    {title: “分类名称”, field: “className”,align:”left”},
    {title: “分类编码”, field: “classCode”},
    // {title: “分类层级”, field: “classIdLevel”},
    {title: “分类状态”, field: “classIdStatus”,templet: ‘#classIdStatusTpl’},
    {title: “创建人”, field: “createUser”},
    {
    title: “创建时间”,
    field: “createTime”,
    templet: ‘<div>{{# if(d.createTime!=null){ }} {{ layui.util.toDateString(d.createTime,\’yyyy-MM-dd HH:mm:ss\’) }} {{# } }}</div>’
    },
    {title: “更新人员”, field: “updateUser”},
    {
    title: “更新时间”,
    field: “updateTime”,
    templet: ‘<div>{{# if(d.updateTime!=null){ }} {{ layui.util.toDateString(d.updateTime,\’yyyy-MM-dd HH:mm:ss\’) }} {{# } }}</div>’
    },
    {title: “操作”, templet: “#updateAndDelete”}
    ]],
    done: function () {
    layer.closeAll(‘loading’);
    }

    })
    };

    renderTable();
    //展开所有
    $(‘#btn-expand’).click(function () {
    //alert(0)
    treetable.expandAll(‘#Lay_category_treeTable’);
    });
    //折叠所有
    $(‘#btn-fold’).click(function () {
    // alert(1)
    treetable.foldAll(‘#Lay_category_treeTable’);
    });
    //刷新表格
    $(‘#btn-refresh’).click(function () {
    renderTable();
    });

    $(‘#btn-search’).click(function () {
    var keyword = $(‘#Lay_toSearch_input’).val();
    //alert(keyword);
    // var searchName = $(‘#Lay_toSearch_input’).val();
    var searchCount = 0;
    $(‘#Lay_category_treeTable’).next(‘.treeTable’).find(‘.layui-table-body tbody tr td’).each(function () {
    $(this).css(‘background-color’, ‘transparent’);
    var text = $(this).text();
    if (keyword != ” && text.indexOf(keyword) >= 0) {
    $(this).css(‘background-color’, ‘rgba(250,230,160,0.5)’);
    if (searchCount == 0) {
    treetable.expandAll(‘#Lay_category_treeTable’);
    $(‘html,body’).stop(true);
    $(‘html,body’).animate({scrollTop: $(this).offset().top – 150}, 500);
    }
    searchCount++;
    }
    });
    if (keyword == ”) {
    layer.msg(“请输入搜索内容”, {icon: 5});
    } else if (searchCount == 0) {
    layer.msg(“没有匹配结果”, {icon: 5});
    }
    });
    });

    //这是一棵树,
    layui.use([‘table’, ‘tree’, “layer”, ‘jquery’, ‘form’], function () {
    var table = layui.table;
    var layer = layui.layer;
    var form = layui.form;
    var tree = layui.tree;
    var $ = layui.jquery;

    $.ajax({
    url: “${pageContext.request.contextPath}/goodscategory/selectTree”,
    success: function (data) {
    //console.log(data);
    //渲染
    var inst1 = tree.render({
    elem: ‘#Lay_category_tree’, //绑定元素
    data: data.data,
    showCheckbox: true
    // accordion:true
    });
    }
    });
    });

    //搜索操作
    function doSearch() {
    //1.获取到输入框中输入的内容
    var searchName = $(‘#Lay_toSearch_input’).val();
    //发送请求,并且接收数据
    layui.use(‘table’, function () {
    var table = layui.table;
    table.reload(‘Lay_back_table’, {
    where: {“platform”: searchName}
    });
    });
    }

    //执行编辑修改
    function toOpenUpdateLayer(classId) {
    //alert(classId);
    //1.获取当前行数据===》发送ajax请求,获取当前行数据
    $.ajax({
    url: “${pageContext.request.contextPath}/goodscategory/selectOne”,
    data: “aid=” + classId,
    success: function (data) {
    $(“#className”).val(data.className);
    $(“#classId”).val(data.classId);
    $(“#classCode”).val(data.classCode);
    // $(“#classIdStatus”).val(data.classIdStatus);
    $(“#classIdStatus”).selected(data.classIdStatus);

    }
    });

    //2.把数据填充到修改弹出层中==>弹出层显示
    layui.use([‘layer’, ‘form’, ‘table’], function () {
    var form = layui.form;
    var layer = layui.layer;
    var table = layui.table;
    var $ = layui.jquery;

    $(“#Lay_select_Level”).hide();
    layer.open({
    title: “修改配置”,
    content: $(“#layuiconfig-form-role”),
    type: 1,
    maxmin: true,
    area: [‘500px’, ‘480px’],
    end:function(){
    window.location.reload();
    }
    });

    $(“#LAY-sysconfig-submit”).hide();
    $(“#updateSubmitBtn”).show();

    //3.提交表单
    form.on(“submit(updateSubmitBtn)”, function (data) {
    // console.log(data);
    $.ajax({
    url: “${pageContext.request.contextPath}/goodscategory/updateGoods”,
    data: data.field,
    type: “post”,
    //4.接收后台修改响应回来的数据;关闭弹出层、提示修改信息、刷新table
    success: function (data) {
    //1.关闭掉添加弹出层
    layer.closeAll(‘page’);
    //2.提示修改成功
    layer.alert(“修改” + data.msg+”,请点击右上角刷新表格后生效!”, {time: 3000});
    //刷新table
    // table.reload(“Lay_category_treeTable”);
    }
    });
    return false;//阻止跳转;
    })
    });

    }

    //执行添加
    function toOpenAddLayer() {
    layui.use([“form”, “layer”, “table”], function () {
    var form = layui.form;
    var layer = layui.layer;
    var table = layui.table;

    layer.open({
    title: “添加配置”,
    content: $(“#layuiconfig-form-role”),
    type: 1,
    maxmin: true,
    area: [‘500px’, ‘480px’],
    end: function () {
    window.location.reload();
    }
    });

    $(“#updateSubmitBtn”).hide();
    $(“#LAY-sysconfig-submit”).show();

    form.on(‘select(classIdLevel)’, function (data) {
    //console.log(data.elem); //得到select原始DOM对象
    console.log(“data.value = “+data.value); //得到被选中的值
    //console.log(data.othis); //得到美化后的DOM对象
    if(data.value == 1){
    // alert(1);
    $(“#Lay_One_Level”).hide();
    $(“#Lay_Two_Level”).hide();
    }
    if (data.value == 2) {
    // alert(2);
    $(“#Lay_One_Level”).show();
    $(“#Lay_Two_Level”).hide();
    $.ajax({
    url: ‘${basepath}goodscategory/selectOneLevel’,
    dataType: ‘json’,
    type: ‘post’,
    success: function (data) {
    $.each(data, function (index, item) {
    //console.log(“000 ” + index);
    //console.log(“111 ” + item);
    $(‘#parentId’).append(new Option(item.className, item.classId));//往下拉菜单里添加元素
    });
    form.render();//菜单渲染 把内容加载进去
    }
    })
    }
    if (data.value == 3) {
    // alert(3);
    $(“#Lay_One_Level”).hide();
    // form.on(‘select(parent_classIdLevel_One)’, function (data2){
    $(“#Lay_Two_Level”).show();
    $.ajax({
    url: ‘${basepath}goodscategory/selectTwoLevel’,
    dataType: ‘json’,
    type: ‘post’,
    success: function (data) {
    $.each(data, function (index, item) {
    //console.log(“000 ” + index);
    //console.log(“111 ” + item);
    $(‘#Two_parentId’).append(new Option(item.className, item.classId));//往下拉菜单里添加元素
    });
    form.render();//菜单渲染 把内容加载进去
    }
    })
    // })
    }
    });

    //当点击提交按钮的时候,会进入到这个函数
    form.on(“submit(LAY-sysconfig-submit)”, function (data) {
    console.log(data.field);
    $.ajax({
    url: “${pageContext.request.contextPath}/goodscategory/addGoodsCategory”,
    data: data.field,
    type: “post”,
    success: function (data) {
    //1.关闭掉添加弹出层
    layer.closeAll(‘page’);
    //2.提示添加成功
    layer.alert(“添加” + data.msg, {time: 3000});
    //3.刷新table
    table.reload(“Lay_back_table”);

    }
    });
    return false;//阻止跳转;
    })
    })
    }

    function doDelete(classId) {
    // alert(classId);
    //确认;如果点击确认删除;否则不删除
    layui.use([‘layer’, ‘table’], function () {
    var table = layui.table;
    var layer = layui.layer;

    layer.confirm(‘确定要删除吗?’, {icon: 3, title: ‘确认删除’}, function (index) {
    $.ajax({
    url: “${pageContext.request.contextPath}/goodscategory/deletecl”,
    data: “aid=” + classId,
    success: function (data) {
    layer.alert(“删除” + data.msg, {time: 2000});
    // table.reload(“Lay_back_table”);
    layer.close(index);
    }
    })
    });
    });
    }

    function doMultiDelete() {
    //获取到选中的内容的id===》table模块中找方法
    layui.use([‘layer’, ‘table’], function () {
    var table = layui.table;
    var layer = layui.layer;
    //获取到选中的数据
    var checkStatus = table.checkStatus(‘Lay_back_table’); //idTest 即为基础参数 id 对应的值
    // console.log(checkStatus.data);//获取选中行的数据
    var data = checkStatus.data;

    if (data.length == 0) {
    layer.alert(“请选中要删除的数据”);
    } else {
    layer.confirm(“确定要删除选中的所有数据”, function (index) {
    //把所有选中的数据的id封装到一个数组中
    var ids = new Array(data.length);
    for (var i = 0; i < ids.length; i++) {
    ids[i] = data[i].id;
    }
    console.log(“ids===” + ids);
    //执行删除操作
    $.ajax({
    url: “${pageContext.request.contextPath}/prefixThird/deleteMany”,
    data: “ids=” + ids,
    success: function (data) {
    //删除确认框关闭掉
    layer.close(index);
    //删除提示
    layer.alert(“删除” + data.msg+”,请点击右上角刷新表格后生效!”, {time: 2000});
    //刷新table
    // table.reload(“Lay_back_table”);
    // renderTable();
    }
    })
    });
    }
    });
    }

    </script>

    </body>
    </html>