javascript - 怎么实现带有checkbox的tree树组件多层嵌套的联动

查看:106
本文介绍了javascript - 怎么实现带有checkbox的tree树组件多层嵌套的联动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

我目前在做带有checkbox的tree组件,我渲染的思路是从父类向子类递归,有children属性就让children调用自己,代码如下

     data = [{
        label: 111,
        children: [{
            label: 222,
        }]
      },  {
        label: 333
      }]
    translate = (content, key, first) => {
        content.forEach((i, index) => {
            i.disabled = this.defaultDisableAll;
            if (this.defaultDisabledList.length > 0) {
                i.disabled = this.defaultDisabledList.indexOf(i[this.nodeKey]) > -1;
            }

            i.key = key + (first ? '' : '-') + (index + 1);

            i.checked = this.defaultCheckedKey.indexOf(i[this.nodeKey]) > -1;

            i.expanded = this.defaultExpandAll;
            if (this.defaultExpandedKey.length > 0) {
                i.expanded = this.defaultExpandedKey.indexOf(i[this.nodeKey]) > -1;
            }

            i.nodeLevel = i.key.split('-').length;
            if (i.checked) {
                treeData.selectedKeys.push(i.key);
            }
            if (i.children && i.children.length > 0) {
                treeData.newDataMap[i.key] = {...i};
                this.translate(i.children, i.key, false);
            } else {
                treeData.newNodes.push({...i});
            }
        })
    };
    ngOnInit() {      
       this.translate(this.data, '', true);
    }

现在需要做checkbox的选择联动,从父类向子类递归的话,需要n-1次递归,感觉很影响性能,有大神给个checkbox多层嵌套联动的解决方案么

解决方案

我的思路是这样的,每次点击一个checkbox的时候,向父级跟children发出通知,
初始化的时候,默认属性就通过设置属性的方式去修改默认的checked,
建立有children属性的newDataMap对象

   calculateCheckState = node => {
        // 向下通知, 如果有的话
        if (node.children) {
            this.informDown(node.children, node.checked);
        }
        // 向上通知
        this.informUp(node);
    };

    informUp = node => {
        // 计算父类的key
        let parent;
        const preKey = node.key.split('-').slice(0, -1).join('-');
        // 如果有父类的话
        if (preKey) {
            parent = treeData.newDataMap[preKey];
            const checkedLength = parent.children.filter(i => i.checked).length;
            // 如果子类选了,却没有全选,或者父类下的子类没有全选的,即有半选的
           if (parent.children.length > checkedLength && checkedLength > 0 ||
                parent.children.filter(i => !!i.indeterminate).length > 0) {
                this.changeCheckState(parent, false, true)
            } else if (parent.children.length === checkedLength) { // 子类全选
                this.changeCheckState(parent, true, false);
            } else if (checkedLength === 0) { // 子类都没有选
                this.changeCheckState(parent, false, false);
            }
        }
        // 如果父类还有父类继续通知
        parent && this.informUp(parent);
    }

    informDown = (child, checked) => {
        child.forEach(i => {
            this.changeCheckState(i.key, checked, false);
            if (i.children) {
                this.informDown(i.children, checked);
            }
        })
    }
    // 找到对应的key的值改掉check状态
    changeCheck = (data, checked, indeterminate) => {
        if (treeData.selectedKeys.includes(data.key)) {
            if (!checked) {
                spliceSelectedKeys(data, this.nodeKey);
            }
        } else {
            if (checked) {
                pushSelectedKey(data, this.nodeKey);
            } else {
                spliceSelectedKeys(data, this.nodeKey);
            }
        }
        data.checked = checked;
        data.indeterminate = indeterminate;
    };

    // 通过索引修改加快速度
    changeCheckState = (node, checked, indeterminate) => {
        const indexList = node.key.split('-');
        let flag = true, data = this.data;
        indexList.forEach(i => {
            if (flag) {
                data = data[parseInt(i, 10) - 1];
                flag = false
            } else {
                data = data['children'][parseInt(i, 10) - 1];
            }
        });
        this.changeCheck(data, checked, indeterminate);
    }

这篇关于javascript - 怎么实现带有checkbox的tree树组件多层嵌套的联动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆