美文网首页
vue递归处理树形数据

vue递归处理树形数据

作者: 全栈的猫南北 | 来源:发表于2023-05-17 16:13 被阅读0次

    先看实现的功能缩略图

    IMG_2259.JPG

    业务需求:

    (1) 省行政区域层级页增加“全国”字段,支持全选和全不选设备权限
    (2) 若子层级的设备权限全部选中,则上级组织展示选中状态,如图1
    (3) 若子层级的设备权限有部分选中,则上级组织展示为半选中状态,如图3,4
    (4) 若子层级的设备权限全部未选中,则上级组织展示为非选中状态,如图2
    ( 5 ) 可直观定位和追溯当前组织所拥有的摄像机权限信息
    ( 6 ) 各层级展示已选数量/全部数量(例:已选2/10),用于展示在各地区已选的设备权限情况,展示格式:已选X/Y,其中X表示当前行政区域内已选择的设备数量,Y表示当前行政区域内全部设备数量

    实现思路

    每一个单元格item都有3种状态标识,selecteTag分为0,1,2。0是未选中,1是半选中,2是选中状态。点击复选框选中和非选中的方法里,同时向上和向下递归处理,向上拿着该item的上级组织的id递归遍历所有上级组织,同时根据012的逻辑给上级组织selecteTag赋值;向下如果该item的存在子级,就把所有子级递归赋值selecteTag为0或者2。同时只对设备进行处理,在选中的数组newCheckList中进行添加或删除操作。

    实现代码

    核心代码
    /** 选中当前的值
                 * @param {Object} e
                 * @param {Object} item 当前项
                 * @param {Object} index 索引
                 */
                checkboxChange(e, item, index) {
                    uni.showLoading({
                        title: '正在加载,请稍候'
                    });
                    console.log('点击chechckBox', e.detail.value, item);
                    let that = this;
                    var data = that.newCheckList;
                    let findIdex = -1; //that.newCheckList.indexOf(item)
                    for (let i in data) {
                        if (data[i].deviceCode == item.deviceCode) {
                            findIdex = i;
                            break;
                        }
    
                    }
                    console.log('选中的数组中的第几个', findIdex);
                    if (e.detail.value && e.detail.value > 0) {
                        // 点击选中
                        if (!item.children && !item.deviceCode) {
                            console.log('选中第一级', item);
                            // 遍历找到item的上级,赋值选中
                            this.partRadioEach(this.parent_data, item.id, 1);
                            //第一级的选中
                            this.parentSelected(item.id, 1);
    
                        } else {
                            that.tree[index].selecteTag = 2
                            if (item.deviceCode && findIdex < 0) {
                                that.newCheckList.push(that.tree[index]);
                            }
                            console.log('选中de', that.newCheckList);
                            var childrendata = that.tree[index].children;
    
                            if (childrendata && childrendata.length > 0) {
                                that.selectedDown(childrendata);
                            }
                        }
    
                    } else {
                        // 点击不选
                        if (!item.children && !item.deviceCode) {
                            console.log('取消选中第一级', item);
                            // 遍历找到item的上级,赋值不选中
                            this.partRadioEach(this.parent_data, item.id, 0);
                            //第一级的不选中
                            this.parentSelected(item.id, 0);
    
                        } else {
                            if (item.deviceCode) {
                                that.newCheckList.splice(findIdex, 1);
                            }
                            that.tree[index].selecteTag = 0
                            var cancledata = that.tree[index].children;
                            console.log('取消删除', cancledata);
                            if (Array.isArray(cancledata) && cancledata.length > 0) {
                                that.deleteDown(cancledata);
                            }
                        }
                    }
    
                    that.parentforEach(that.parent_data, item.pid);
    
                    console.log('最后的选中数组', this.newCheckList, item.pid);
                    that.checckNewList();
                    this.topSelString = this.getTopChooseItem();
                    that.$forceUpdate(); //强制更新数据
                    uni.hideLoading();
                },
    
    第一个item的选中和非选中事件,因为第一个item在上级也存在
        //遍历找到选中的item,赋值选中或不选中
                partRadioEach(arr, itemid, tag) {
                    for (let i = 0; i < arr.length; i++) {
                        if (arr[i].id == itemid) {
                            if (tag == 1) {
                                arr[i].selecteTag = 2;
    
                            } else {
                                arr[i].selecteTag = 0;
                            }
                        }
                        if (Array.isArray(arr[i].children) && arr[i].children.length > 0) {
                            this.partRadioEach(arr[i].children, itemid, tag);
                        }
                    }
                },
    

    只对设备进行处理,在选中的数组newCheckList中进行添加或删除操作

    //第一个item的选中和非选中,只对设备进行处理,在选中的数组newCheckList中进行添加或删除操作
                parentSelected(pid, tag) {
                    for (let i in this.tree) {
                        var treechildata = this.tree[i].children;
                        if (tag == 1) {
                            let item = this.tree[i];
                            item.selecteTag = 2;
                            //判断是否是设备
                            if (item.deviceCode) {
                                let findIdex = -1;
                                for (let i in this.newCheckList) {
                                    if (this.newCheckList[i].deviceCode == item.deviceCode) {
                                        findIdex = i;
                                        break;
                                    }
                                }
                                if (findIdex < 0) {
                                    this.newCheckList.push(item);
                                }
                            }
                            if (treechildata && treechildata.length > 0) {
                                this.selectedDown(treechildata);
                            }
                        } else {
                            this.tree[i].selecteTag = 0;
                            var List = this.newCheckList;
                            console.log('删除第一、选中的数组', this.newCheckList);
                            let Idex = -1;
                            for (let j in List) {
                                if (List[j].deviceCode) {
                                    if (List[j].deviceCode == this.tree[i].deviceCode) {
                                        Idex = j;
                                        this.newCheckList.splice(Idex, 1);
                                        break;
                                    }
                                }
                            }
                            if (treechildata && treechildata.length > 0) {
                                this.deleteDown(treechildata);
                            }
                        }
                    };
    
                },
    

    向下递归选中

        //向下递归选中最底层设备
            selectedDown(arr) {
                for (let i = 0; i < arr.length; i++) {
                    let item = arr[i];
                    item.selecteTag = 2;
                    //如果是设备的话,才加入选中的数组
                    if (item.deviceCode) {
                        let findIdex = -1;
                        for (let i in this.newCheckList) {
                            if (this.newCheckList[i].deviceCode == item.deviceCode) {
                                findIdex = i;
                                break;
                            }
                        }
                        if (findIdex < 0) {
                            this.newCheckList.push(item);
                        }
                    }
                    if (Array.isArray(arr[i].children) && arr[i].children.length > 0) {
                        this.selectedDown(arr[i].children);
                    }
                }
            },
    

    向下递归删除

        //向下递归删除
            deleteDown(data) {
                var List = this.newCheckList;
                console.log('删除、选中的数组', this.newCheckList);
                for (let i in data) {
                    if (Array.isArray(data) && data.length > 0) {
                        let Idex = -1;
                        for (let j in List) {
                            if (List[j].deviceCode) {
                                if (List[j].deviceCode == data[i].deviceCode) {
                                    Idex = j;
                                    this.newCheckList.splice(Idex, 1);
                                    break;
                                }
                            }
    
                        }
                        data[i].selecteTag = 0;
                        if (Array.isArray(data[i].children) && data[i].children.length > 0) {
                            this.deleteDown(data[i].children);
                        }
                    }
                };
    
                console.log('向下删除循环后的选中数组', this.newCheckList);
            },
    

    根据上级组织id,递归遍历所有上级,根据子层级的设备权限是否选中,给上级组织状态赋值

            //遍历所有上级赋值
                parentforEach(arr, itempid) {
                    for (let i = 0; i < arr.length; i++) {
                        //是上级的处理
                        if (arr[i].id == itempid) {
    
                            var sum = 0;
                            var subdata = arr[i].children //.splice(0, 1);
                            for (let j in subdata) {
                                sum += subdata[j].selecteTag ? subdata[j].selecteTag : 0;
                            }
                            sum = sum - (subdata[0].selecteTag ? subdata[0].selecteTag : 0);
                            console.log('遍历父级', sum, arr[i].children.length);
                            if (sum >= (arr[i].children.length - 1) * 2) {
                                // 子级全部选中时上级组织也选中
                                arr[i].selecteTag = 2;
                                if (arr[i].children[0]) {
                                    arr[i].children[0].selecteTag = 2;
                                    console.log('选中上级', arr[i]);
                                }
                            } else if (sum == 0) {
                                // 子级全部不选中时上级组织也不选中
                                console.log('不选中', arr[i]);
                                arr[i].selecteTag = 0
                                if (Array.isArray(arr[i].children) && arr[i].children.length > 0) {
                                    arr[i].children[0].selecteTag = 0;
                                }
                            } else {
                                // 子级有选中且非全部选中的时候,上级组织时半选中
                                console.log('半选中', arr[i]);
                                arr[i].selecteTag = 1;
                                if (Array.isArray(arr[i].children) && arr[i].children.length > 0) {
                                    arr[i].children[0].selecteTag = 1;
                                }
                            }
                            this.$forceUpdate(); //强制更新数据
                            if (arr[i].pid && Number(arr[i].pid) != 0) {
                                this.parentforEach(this.parent_data, arr[i].pid);
                            }
                            return;
                        }
    
                        if (Array.isArray(arr[i].children) && arr[i].children.length > 0) {
                            this.parentforEach(arr[i].children, itempid);
                        }
                    }
                },
    

    相关文章

      网友评论

          本文标题:vue递归处理树形数据

          本文链接:https://www.haomeiwen.com/subject/khabcdtx.html