layui tree组件--取消子关联父,且保持选中项处于展开状态

1,754 阅读3分钟

layui自带的tree组件,默认情况下,父子节点是关联的。但是某些业务场景下,我们需要取消父子关联,或者只取消子关联父。我的业务需求要解决的问题包括如下几个方面:

1. 取消子对父的关联,即当选择父节点下的子节点,或取消勾选子节点,均不会对父节点有任何影响.

首先找到layui文件夹modules里面的tree.js,把setCheckbox方法里面的内容改成如下内容:

image.png

image.png 上面改造的作用是取消子级对父级的关联,无论子集正反选,均不对父级产生影响。

2.勾选项默认展开

  • 我的业务需求是在弹出层中展示用户的管辖公司,勾选后可以获取一个或多个公司的数据.
  • 当打开弹窗时,被勾选中的项及其父项是需要展开的,通过官方文档可以知道,与节点展开有关的属性为:spread,当其为true时,对应数据项展开(这里注意一点,当被勾选的是最底层,即没有子级,给其加上spread:true,节点也不会展开,需要给其父元素加spread:true)
  • 可以通过递归来获取树形数据,获取每一项的id,同时再用被勾选的id去对比,即可判断出哪些项被勾选,从而加上spread。
  • 这里我在tree.js中自定义了一个获取用户勾选项的id的方法,如下图:

image.png

  • 在页面的js中定义一个数组,用于存放被勾选的id,再调用getCheckedId方法存入id,最后调用封装好的函数进行对比添加spread:true,具体如下:
```var arr = [] //存储选中的id
// 辅助函数:向上遍历树结构并给遇到的每个父节点添加spread: true  
function setSpreadUpward(company) {
    while (company) {
        company.spread = true; // 设置当前节点的spread为true  
        company = company.parent; // 向上移动到父节点  
    }
}

// 递归函数,用于遍历树形结构中的子公司  
function traverseTree(companies, arr, parent = null) {
    companies.forEach(function (company) {
        // 设置父节点引用(仅第一次遍历时需要)  
        if (parent) {
            company.parent = parent;
        }

        // 检查当前节点的orgNo是否在arr数组中  
        if (arr.includes(company.myId)) {
            setSpreadUpward(company); // 如果在,则向上设置spread: true  
        } else if (company.spread) {
            delete company.spread; // 如果不在但之前设置了spread: true,则移除  
        }

        // 递归遍历子公司(如果存在)  
        if (company.treeCompanies) {
            traverseTree(company.treeCompanies, arr, company);
        }
    });
}
   layui.use('tree', function () {
            tree = layui.tree;
            tree.render({ // 初始化tree组件
                elem: "#customContent",
                data: companyLists,
                showCheckbox: true,  // 是否显示复选框
                contact: false,
                id: 'test',
                isJump: false,
                customName: {
                    id: 'myId',
                    title: 'myName',
                    children: 'treeCompanies'
                },
                oncheck: function (obj) {
                    arr = tree.getCheckedId('test'); //获取点击的节点
                    traverseTree(companyLists, arr);
                }
            })
        })
        var customLayerIndex = layer.open({
            type: 1,
            title: false,
            shadeClose: false,
            closeBtn: false,
            anim: 'left',
            area: ['90%', '100%'],
            offset: 'lt', // 弹出层的位置,lt 表示 left top,即左上角对齐  
            shift: 0, // 弹出层的坐标偏移量,可以微调位置  
            content: $("#customLayerContent"),
            success: function (layero, index) {
                var shade = $('.layui-layer-shade'); 
                shade.on('click', function (e) {
                    e.stopPropagation(); // 阻止事件冒泡  
                    return false
                });
                $(layero).css('left', '0px'); // 确保弹出层靠左  
                $('#closeDialog', '#customLayerContent', layero).on('click', function () {
                    layer.close(customLayerIndex); // 点击关闭按钮时关闭弹窗  
                    $('#checkBtn', layero).off('click');// 清理checkBtn的点击事件处理器  
                });
            }
        })

3. 打开弹窗,树状图保持上一次的选中状态

  • 这里需要注意一点,由于我们只取消了子勾选父,没有取消父勾选子,所以当勾选了父级,再把子集全部取消勾选后,当再次打开弹窗,会发现原本取消的子级又被勾选上了。要解决这个问题,可以再渲染完tree组件后,调用之前在tree.js中定义的setChecked方法,以此来设置勾选状态。

image.png

image.png

如果你也在业务中遇到以上问题,不妨一试,代码均经过实际项目检验,某门忒.