vue遞歸處理樹形數(shù)據(jù)

先看實(shí)現(xiàn)的功能縮略圖

IMG_2259.JPG

業(yè)務(wù)需求:

(1) 省行政區(qū)域?qū)蛹?jí)頁增加“全國”字段,支持全選和全不選設(shè)備權(quán)限
(2) 若子層級(jí)的設(shè)備權(quán)限全部選中涯冠,則上級(jí)組織展示選中狀態(tài),如圖1
(3) 若子層級(jí)的設(shè)備權(quán)限有部分選中逼庞,則上級(jí)組織展示為半選中狀態(tài)功偿,如圖3,4
(4) 若子層級(jí)的設(shè)備權(quán)限全部未選中往堡,則上級(jí)組織展示為非選中狀態(tài)械荷,如圖2
( 5 ) 可直觀定位和追溯當(dāng)前組織所擁有的攝像機(jī)權(quán)限信息
( 6 ) 各層級(jí)展示已選數(shù)量/全部數(shù)量(例:已選2/10),用于展示在各地區(qū)已選的設(shè)備權(quán)限情況虑灰,展示格式:已選X/Y吨瞎,其中X表示當(dāng)前行政區(qū)域內(nèi)已選擇的設(shè)備數(shù)量,Y表示當(dāng)前行政區(qū)域內(nèi)全部設(shè)備數(shù)量

實(shí)現(xiàn)思路

每一個(gè)單元格item都有3種狀態(tài)標(biāo)識(shí)穆咐,selecteTag分為0颤诀,1,2对湃。0是未選中崖叫,1是半選中,2是選中狀態(tài)拍柒。點(diǎn)擊復(fù)選框選中和非選中的方法里心傀,同時(shí)向上和向下遞歸處理,向上拿著該item的上級(jí)組織的id遞歸遍歷所有上級(jí)組織拆讯,同時(shí)根據(jù)012的邏輯給上級(jí)組織selecteTag賦值脂男;向下如果該item的存在子級(jí),就把所有子級(jí)遞歸賦值selecteTag為0或者2种呐。同時(shí)只對(duì)設(shè)備進(jìn)行處理宰翅,在選中的數(shù)組newCheckList中進(jìn)行添加或刪除操作。

實(shí)現(xiàn)代碼

核心代碼
/** 選中當(dāng)前的值
             * @param {Object} e
             * @param {Object} item 當(dāng)前項(xiàng)
             * @param {Object} index 索引
             */
            checkboxChange(e, item, index) {
                uni.showLoading({
                    title: '正在加載,請(qǐng)稍候'
                });
                console.log('點(diǎn)擊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('選中的數(shù)組中的第幾個(gè)', findIdex);
                if (e.detail.value && e.detail.value > 0) {
                    // 點(diǎn)擊選中
                    if (!item.children && !item.deviceCode) {
                        console.log('選中第一級(jí)', item);
                        // 遍歷找到item的上級(jí)爽室,賦值選中
                        this.partRadioEach(this.parent_data, item.id, 1);
                        //第一級(jí)的選中
                        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 {
                    // 點(diǎn)擊不選
                    if (!item.children && !item.deviceCode) {
                        console.log('取消選中第一級(jí)', item);
                        // 遍歷找到item的上級(jí)汁讼,賦值不選中
                        this.partRadioEach(this.parent_data, item.id, 0);
                        //第一級(jí)的不選中
                        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('最后的選中數(shù)組', this.newCheckList, item.pid);
                that.checckNewList();
                this.topSelString = this.getTopChooseItem();
                that.$forceUpdate(); //強(qiáng)制更新數(shù)據(jù)
                uni.hideLoading();
            },
第一個(gè)item的選中和非選中事件,因?yàn)榈谝粋€(gè)item在上級(jí)也存在
    //遍歷找到選中的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);
                    }
                }
            },

只對(duì)設(shè)備進(jìn)行處理嘿架,在選中的數(shù)組newCheckList中進(jìn)行添加或刪除操作

//第一個(gè)item的選中和非選中卜录,只對(duì)設(shè)備進(jìn)行處理,在選中的數(shù)組newCheckList中進(jìn)行添加或刪除操作
            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;
                        //判斷是否是設(shè)備
                        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('刪除第一眶明、選中的數(shù)組', 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);
                        }
                    }
                };

            },

向下遞歸選中

    //向下遞歸選中最底層設(shè)備
        selectedDown(arr) {
            for (let i = 0; i < arr.length; i++) {
                let item = arr[i];
                item.selecteTag = 2;
                //如果是設(shè)備的話艰毒,才加入選中的數(shù)組
                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('刪除、選中的數(shù)組', 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('向下刪除循環(huán)后的選中數(shù)組', this.newCheckList);
        },

根據(jù)上級(jí)組織id搜囱,遞歸遍歷所有上級(jí)丑瞧,根據(jù)子層級(jí)的設(shè)備權(quán)限是否選中,給上級(jí)組織狀態(tài)賦值

        //遍歷所有上級(jí)賦值
            parentforEach(arr, itempid) {
                for (let i = 0; i < arr.length; i++) {
                    //是上級(jí)的處理
                    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('遍歷父級(jí)', sum, arr[i].children.length);
                        if (sum >= (arr[i].children.length - 1) * 2) {
                            // 子級(jí)全部選中時(shí)上級(jí)組織也選中
                            arr[i].selecteTag = 2;
                            if (arr[i].children[0]) {
                                arr[i].children[0].selecteTag = 2;
                                console.log('選中上級(jí)', arr[i]);
                            }
                        } else if (sum == 0) {
                            // 子級(jí)全部不選中時(shí)上級(jí)組織也不選中
                            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 {
                            // 子級(jí)有選中且非全部選中的時(shí)候蜀肘,上級(jí)組織時(shí)半選中
                            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(); //強(qiáng)制更新數(shù)據(jù)
                        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);
                    }
                }
            },
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绊汹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子扮宠,更是在濱河造成了極大的恐慌西乖,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坛增,死亡現(xiàn)場(chǎng)離奇詭異获雕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)收捣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門届案,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人罢艾,你說我怎么就攤上這事楣颠。” “怎么了咐蚯?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵童漩,是天一觀的道長。 經(jīng)常有香客問我春锋,道長矫膨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任看疙,我火速辦了婚禮豆拨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘能庆。我一直安慰自己,他們只是感情好脚线,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布搁胆。 她就那樣靜靜地躺著南吮,像睡著了一般歉胶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天减途,我揣著相機(jī)與錄音,去河邊找鬼状勤。 笑死吴侦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的杂靶。 我是一名探鬼主播梆惯,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼吗垮!你這毒婦竟也來了垛吗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤烁登,失蹤者是張志新(化名)和其女友劉穎怯屉,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饵沧,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锨络,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狼牺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片足删。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锁右,靈堂內(nèi)的尸體忽然破棺而出失受,到底是詐尸還是另有隱情,我是刑警寧澤咏瑟,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布拂到,位于F島的核電站,受9級(jí)特大地震影響码泞,放射性物質(zhì)發(fā)生泄漏兄旬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一余寥、第九天 我趴在偏房一處隱蔽的房頂上張望领铐。 院中可真熱鬧,春花似錦宋舷、人聲如沸绪撵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽音诈。三九已至幻碱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間细溅,已是汗流浹背褥傍。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喇聊,地道東北人恍风。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像誓篱,于是被迫代替她去往敵國和親朋贬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容