LayUi 树形组件tree 实现懒加载模式,展开父节点时异步加载子节点数据

LayUi框架中树形组件tree官方还在持续完善中,目前最新版本为v2.5.5

官方树形组件目前还不支持懒加载方式,之前我修改一版是通过reload重载实例方法填充子节点数据方式,因为递归页面元素时存在效率问题,最终放弃升级。

本次重新star了官方最新tree.js源码,在其基础上扩展了子节点懒加载模式方法,data数据参数中增加了lazy: true,开启懒加载模式,需要配合spread事件使用。

部分源码修改截图:

 

 

调用例子:

 

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta http-equiv="hg-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta http-equiv="Cache-Control" content="no-siteapp" />
    <link rel="stylesheet" href="./css/font.css">
    <link rel="stylesheet" href="../lib/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="./lib/admin/admin.css" media="all">
    <link rel="stylesheet" href="./lib/Scrollbar/jquery.scrollbar.css">
    <script type="text/javascript" src="./lib/admin/jquery-1.9.1.min.js"></script>
    <script type="text/javascript" src="./lib/Scrollbar/jquery.scrollBar.js"></script>
    <script type="text/javascript" src="./lib/layui/layui.js"></script>
    <script type="text/javascript" src="./lib/admin/admin.js"></script>
    <!--[if lt IE 9]>
          <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
          <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
        <![endif]-->
    <style>
        .demo-tree{
            width: 500px; height: 200px;
        }
        .demo-tree-box{
            width: 500px; height: 200px;border: 1px #eee solid;overflow-y: auto;
        }
        .demo-input-tree{
            height: auto;
            width: 100%;
            display: none;
            position: absolute;
            top: 100%;
            background-color: #fff;
            z-index: 100;
            max-height: 400px;
        }
        .layui-input{
            width: 500px;
            cursor: pointer;
        }
    </style>
</head>

<body class="layui-body-content">
    <div class="layui-fluid">
        <div class="layui-card">
            <div class="layui-form layui-card-header layui-card-header-auto">
                <div class="layui-form-item">
                    <label class="layui-form-label">部门:</label>
                    <div class="layui-inline">
                        <input type="text" name="dept" lay-verify="required" placeholder="请选择部门" autocomplete="off" class="layui-input" readonly="true">
                        <div id="treeinputid" class="demo-input-tree demo-tree-box"></div>
                    </div>
                    <div class="layui-inline layui-show-xs-block">
                        <button class="layui-btn layui-btn-lg layui-btn-normal" lay-submit lay-filter="sreach"><i
                                class="layui-icon layui-icon-lg">&#xe615;</i></button>
                    </div>
                </div>
            </div>
            <div class="layui-card-body">
                <div class="layui-card-header">
                    <button class="layui-btn layui-btn-lg layui-btn-normal"
                        onclick="getChecked()"><i
                            class="layui-icon">&#xe654;</i>获取选中</button>
                    <button class="layui-btn layui-btn-lg layui-btn-warm" onclick="setChecked()"><i
                            class="layui-icon">&#xe642;</i>设置节点勾选</button>
                    <button class="layui-btn layui-btn-lg layui-btn-danger" onclick="reload()"><i
                            class="layui-icon">&#xe640;</i>实例重载</button>
                </div>
                <div class="demo-tree">
                    <div id="treeid" class="demo-tree demo-tree-box"></div>
                </div>
            </div>
        </div>
        <div class="layui-floor">
            <blockquote class="layui-elem-quote layui-quote-nm">Copyright©2019-2020, 本系统由@一如既往,提供技术支持!
            </blockquote>
        </div>
    </div>
</body>
<script>
    //初始化
    layui.use(['tree'], function () {
        var tree = layui.tree;
        //treeid
        var inst1 = tree.render({
            elem: '#treeid',
            id: 'treeid', //定义索引
            showCheckbox: true, //是否显示复选框
            showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
            accordion: false, //是否开启手风琴模式,默认 false
            onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
            isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
            data: [{
                id: 'hg-100',
                field: '1',
                level: '1',
                title: '父节点100',
                spread: true,
                children: [{
                    id: 'hg-100101',
                    field: '3',
                    level: '2',
                    title: '子节点100101',
                    children: [{
                        id: 'hg-100101101',
                        field: '4',
                        level: '3',
                        title: '子节点100101101'
                    }, {
                        id: 'hg-100101102',
                        field: '5',
                        level: '3',
                        title: '子节点100101102'
                    }, {
                        id: 'hg-100101103',
                        field: '6',
                        level: '3',
                        title: '子节点100101103'
                    }]
                }]
            }, {
                id: 'hg-200',
                field: '2',
                level: '1',
                title: '父节点200',
                lazy: true
            }],
            text: {
                defaultNodeName: '无数据',
                none: '加载数据失败!'
            },
            click: function (obj) {
                console.log(obj.data); //得到当前点击的节点数据
                console.log(obj.state); //得到当前节点的展开状态:open、close、normal
                console.log(obj.elem); //得到当前节点元素
                console.log(obj.data.children); //当前节点下是否有子节点
            },
            oncheck: function (obj) {
                console.log(obj.data); //得到当前点击的节点数据
                console.log(obj.checked); //得到当前节点的展开状态:open、close、normal
                console.log(obj.elem); //得到当前节点元素
            },
            spread: function (obj) {
                console.log(obj);
                if(obj.state=='open'){
                    setTimeout(() => {
                        tree.lazytree(inst1.config.id, obj.elem, getTreeJson(obj.data.id));
                    }, 2000);
                }
            }
        });

        //treeinput
        var inst2;
        $("[name='dept']").on("click",function (e) {
            e.stopPropagation();
            const deprt = this;
            if(!inst2){
                inst2 = tree.render({
                    elem: '#treeinputid',
                    id: 'treeinputid', //定义索引
                    showCheckbox: true, //是否显示复选框
                    showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
                    accordion: false, //是否开启手风琴模式,默认 false
                    onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
                    isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
                    data: [{
                        id: 'hg-100',
                        field: '1',
                        level: '1',
                        title: '父节点100',
                        spread: true,
                        children: [{
                            id: 'hg-100101',
                            field: '3',
                            level: '2',
                            title: '子节点100101',
                            children: [{
                                id: 'hg-100101101',
                                field: '4',
                                level: '3',
                                title: '子节点100101101'
                            }, {
                                id: 'hg-100101102',
                                field: '5',
                                level: '3',
                                title: '子节点100101102'
                            }, {
                                id: 'hg-100101103',
                                field: '6',
                                level: '3',
                                title: '子节点100101103'
                            }]
                        }]
                    }, {
                        id: 'hg-200',
                        field: '2',
                        level: '1',
                        title: '父节点200',
                        lazy: true
                    }],
                    text: {
                        defaultNodeName: '无数据',
                        none: '加载数据失败!'
                    },
                    click: function (obj) {
                        console.log(obj.data); //得到当前点击的节点数据
                        console.log(obj.state); //得到当前节点的展开状态:open、close、normal
                        console.log(obj.elem); //得到当前节点元素
                        console.log(obj.data.children); //当前节点下是否有子节点
                    },
                    oncheck: function (obj) {
                        var checkData = tree.getChecked(inst2.config.id);
                        var map = getmap(checkData);
                        $(deprt).val(map.value.join(','));
                    },
                    spread: function (obj) {
                        console.log(obj);
                        if(obj.state=='open'){
                            setTimeout(() => {
                                tree.lazytree(inst2.config.id, obj.elem, getTreeJson(obj.data.id));
                            }, 2000);
                        }
                    }
                });
            }
            $("#treeinputid").toggle();
        })


        //监听表单提交事件
        hg.form.onsubmit('sreach', function (data) {
            $("#treeinputid").hide();
            var checkData = tree.getChecked(inst2.config.id);
            var map = getmap(checkData);
            var init = map.result;
            hg.msg(JSON.stringify(init));
        });

        const getmap = (target, result = []) => {
            layui.each(target,(i,e)=>{
                e.id && result.push({id:e.id,title:e.title});
                e.children && getmap(e.children, result);
            });
            let titles = result.map(e=>{return e.title});
            return {value:titles,result:result};
        };

    });

    

    // 模拟后台返回数据
    function getTreeJson(id) {
        if (id === 'hg-200') {
            return [{
                id: 'hg-200101',
                level: '2',
                title: '子节点200101'
            }, {
                id: 'hg-200102',
                level: '2',
                title: '子节点200102',
                lazy: true
            }];
        }
        if (id === 'hg-200102') {
            return [{
                id: 'hg-200102101',
                level: '3',
                title: '子节点200102101'
            }, {
                id: 'hg-200102102',
                level: '3',
                title: '子节点200102102',
                lazy: true
            }];
        }
        if (id === 'hg-200102102') {
            return [{
                id: 'hg-200102102101',
                level: '4',
                title: '子节点200102102101'
            }, {
                id: 'hg-200102102102',
                level: '4',
                title: '子节点200102102102',
            }];
        }
    }
    //获得选中的节点 
    function getChecked(){
        layui.use(['tree'], function () {
            var tree = layui.tree;
            var checkData = tree.getChecked('treeid');
            hg.msg(JSON.stringify(checkData));
        });
    }
    //设置节点勾选
    function setChecked(){
        layui.use(['tree'], function () {
            var tree = layui.tree;
            tree.setChecked('treeid', ['hg-100101101','hg-100101102']);
        });
    }
    //实例重载
    function reload(){
        layui.use(['tree'], function () {
            var tree = layui.tree;
            tree.reload('treeid', {
            });
        });
    }
        
</script>

</html>
View Code

 

 

 

 

<script>
    //初始化
    layui.use(['tree'], function () {
        var tree = layui.tree;
        //treeid
        var inst1 = tree.render({
            elem: '#treeid',
            id: 'treeid', //定义索引
            showCheckbox: true, //是否显示复选框
            showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
            accordion: false, //是否开启手风琴模式,默认 false
            onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
            isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
            data: [{
                id: 'hg-100',
                field: '1',
                level: '1',
                title: '父节点100',
                spread: true,
                children: [{
                    id: 'hg-100101',
                    field: '3',
                    level: '2',
                    title: '子节点100101',
                    children: [{
                        id: 'hg-100101101',
                        field: '4',
                        level: '3',
                        title: '子节点100101101'
                    }, {
                        id: 'hg-100101102',
                        field: '5',
                        level: '3',
                        title: '子节点100101102'
                    }, {
                        id: 'hg-100101103',
                        field: '6',
                        level: '3',
                        title: '子节点100101103'
                    }]
                }]
            }, {
                id: 'hg-200',
                field: '2',
                level: '1',
                title: '父节点200',
                lazy: true
            }],
            text: {
                defaultNodeName: '无数据',
                none: '加载数据失败!'
            },
            click: function (obj) {
                console.log(obj.data); //得到当前点击的节点数据
                console.log(obj.state); //得到当前节点的展开状态:open、close、normal
                console.log(obj.elem); //得到当前节点元素
                console.log(obj.data.children); //当前节点下是否有子节点
            },
            oncheck: function (obj) {
                console.log(obj.data); //得到当前点击的节点数据
                console.log(obj.checked); //得到当前节点的展开状态:open、close、normal
                console.log(obj.elem); //得到当前节点元素
            },
            spread: function (obj) {
                console.log(obj);
                if(obj.state=='open'){
                    setTimeout(() => {
                        tree.lazytree(inst1.config.id, obj.elem, getTreeJson(obj.data.id));
                    }, 2000);
                }
            }
        });

        //treeinput
        var inst2;
        $("[name='dept']").on("click",function (e) {
            e.stopPropagation();
            const deprt = this;
            if(!inst2){
                inst2 = tree.render({
                    elem: '#treeinputid',
                    id: 'treeinputid', //定义索引
                    showCheckbox: true, //是否显示复选框
                    showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
                    accordion: false, //是否开启手风琴模式,默认 false
                    onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
                    isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
                    data: [{
                        id: 'hg-100',
                        field: '1',
                        level: '1',
                        title: '父节点100',
                        spread: true,
                        children: [{
                            id: 'hg-100101',
                            field: '3',
                            level: '2',
                            title: '子节点100101',
                            children: [{
                                id: 'hg-100101101',
                                field: '4',
                                level: '3',
                                title: '子节点100101101'
                            }, {
                                id: 'hg-100101102',
                                field: '5',
                                level: '3',
                                title: '子节点100101102'
                            }, {
                                id: 'hg-100101103',
                                field: '6',
                                level: '3',
                                title: '子节点100101103'
                            }]
                        }]
                    }, {
                        id: 'hg-200',
                        field: '2',
                        level: '1',
                        title: '父节点200',
                        lazy: true
                    }],
                    text: {
                        defaultNodeName: '无数据',
                        none: '加载数据失败!'
                    },
                    click: function (obj) {
                        console.log(obj.data); //得到当前点击的节点数据
                        console.log(obj.state); //得到当前节点的展开状态:open、close、normal
                        console.log(obj.elem); //得到当前节点元素
                        console.log(obj.data.children); //当前节点下是否有子节点
                    },
                    oncheck: function (obj) {
                        var checkData = tree.getChecked(inst2.config.id);
                        var map = getmap(checkData);
                        $(deprt).val(map.value.join(','));
                    },
                    spread: function (obj) {
                        console.log(obj);
                        if(obj.state=='open'){
                            setTimeout(() => {
                                tree.lazytree(inst2.config.id, obj.elem, getTreeJson(obj.data.id));
                            }, 2000);
                        }
                    }
                });
            }
            $("#treeinputid").toggle();
        })


        //监听表单提交事件
        hg.form.onsubmit('sreach', function (data) {
            $("#treeinputid").hide();
            var checkData = tree.getChecked(inst2.config.id);
            var map = getmap(checkData);
            var init = map.result;
            hg.msg(JSON.stringify(init));
        });

        const getmap = (target, result = []) => {
            layui.each(target,(i,e)=>{
                e.id && result.push({id:e.id,title:e.title});
                e.children && getmap(e.children, result);
            });
            let titles = result.map(e=>{return e.title});
            return {value:titles,result:result};
        };

    });

    

    // 模拟后台返回数据
    function getTreeJson(id) {
        if (id === 'hg-200') {
            return [{
                id: 'hg-200101',
                level: '2',
                title: '子节点200101'
            }, {
                id: 'hg-200102',
                level: '2',
                title: '子节点200102',
                lazy: true
            }];
        }
        if (id === 'hg-200102') {
            return [{
                id: 'hg-200102101',
                level: '3',
                title: '子节点200102101'
            }, {
                id: 'hg-200102102',
                level: '3',
                title: '子节点200102102',
                lazy: true
            }];
        }
        if (id === 'hg-200102102') {
            return [{
                id: 'hg-200102102101',
                level: '4',
                title: '子节点200102102101'
            }, {
                id: 'hg-200102102102',
                level: '4',
                title: '子节点200102102102',
            }];
        }
    }
    //获得选中的节点 
    function getChecked(){
        layui.use(['tree'], function () {
            var tree = layui.tree;
            var checkData = tree.getChecked('treeid');
            hg.msg(JSON.stringify(checkData));
        });
    }
    //设置节点勾选
    function setChecked(){
        layui.use(['tree'], function () {
            var tree = layui.tree;
            tree.setChecked('treeid', ['hg-100101101','hg-100101102']);
        });
    }
    //实例重载
    function reload(){
        layui.use(['tree'], function () {
            var tree = layui.tree;
            tree.reload('treeid', {
            });
        });
    }
        
</script>

 

 

 

 

 

 

 【HG-Layui-UI通用后台管理框架V1.0版】

下载地址:

https://www.cnblogs.com/han1982/p/12003454.html

tree.js 下载地址在回复区可见。(layui-v2.5.5版本替换tree.js可用)

 

posted @ 2019-09-17 17:32  hg一如既往  阅读(23162)  评论(39编辑  收藏  举报