前言
前段時間做一個vue項目過程中遇到element-ui的el-checkbox循環嵌套的問題,後參考網上的文章加之自己的修改,現做一個記錄分享。我這裏僅僅是以一個二級菜單爲例,三級菜單也可以做相應的修改。
最終效果圖
主要需求
- 實現多選框層級嵌套
- 當選中一個二級子菜單的時候,其對應的上級菜單也選中
- 若二級子菜單無一個選中,則對應的一級菜單也不是選中狀態
- 當一級菜單發生點擊事件時,若原本爲選中狀態,則取消選中,若該菜單下有二級子菜單,所有子菜單也取消選中狀態;若原本爲未選中狀態,則改爲選中狀態,若該菜單下有二級子菜單,所有子菜單也改爲選中狀態。
- 實現已有的選擇記錄的復現。
實現過程
1.data數據
data() {
return {
menu: [] //所有的菜單數組,
menusIds: [] //已選的菜單id數組
}
}
2.html部分
要實現一個嵌套的效果,每一個一級菜單應該是一個單獨的模塊,二級菜單包裹在一級菜單下面,實現一個附屬的效果,添加一個縮進,具體代碼如下:
<div class="checkbox-table" v-for="(item, indexkey) in menu" :key="item.id">
<template>
<el-checkbox class="check1" style="font-weight: 600;margin-bottom: 15px " v-model='menusIds' :label="item.id" @change='handleCheck(1,indexkey)'>
{{item.name}}
</el-checkbox>
<div style="margin-bottom: 20px;">
<div v-for="list in item.children" class="line-check" :key="list.id" style="display: inline-block; margin-left: 20px;margin-bottom: 20px;" >
<el-checkbox class="check2" @change='handleCheck(2,indexkey)' v-model="menusIds" :label="list.id">
{{list.name}}
</el-checkbox>
</div>
</div>
</template>
</div>
3.點擊事件的處理
提示:element-ui的el-checkbox默認change事件在這裏千萬不能使用,不適合這個使用場景,循環嵌套的change事件必須要自定義
。
自定義的change事件必須標明是哪個層級發生了點擊事件。
handlecheck(type, a = 0);第一個參數是來表示哪個層級發生了點擊事件。(如果是多層級的話,這個函數的參數還要多增加一些,要標明當前點擊的是哪個層級,及他對應的所有父祖層級都應該用參數標明。)
把所有選中的菜單的id放到一個數組裏面,作爲el-checkbox的model數據,只有當着el-checkbox的id在menusIds裏時,纔會有選中的狀態,否則是未選中的。依照這個方法,我們只要在點擊這個某個菜單時,判斷他是否在menusIds裏存在,若存在,則剔除,不存在則把這個id放進去。但是這個過程中有兩個注意點:
1 若是二級子菜單的點擊,要去判斷該父級下是否還有二級子菜單是選中的狀態,若無,則要順帶把該父級菜單的id也從menusIds中剔除。
2. 若是父級的點擊,若原來是選中的狀態,剔除該父級菜單id的同時,還要剔除其下面所有子集菜單的id;若原來是未選中的,則點擊之後添加完該父級菜單的id,還要遍歷其下面所有的子集,並把他們的id添加進menusIds。
具體代碼如下:
// 處理選擇事件
handleCheck(type, a = 0) { // 多選框
let self = this;
if (type == 2) { // 二級菜單點擊
let index = 0;
self.menu[a].children.map(item => {
if (self.menusIds.indexOf(item.id) > -1) {
index += 1;
}
})
if (index > 0) {
if (self.menusIds.indexOf(self.menu[a].id) < 0) {
self.menusIds.push(self.menu[a].id);
}
} else {
if (self.menusIds.indexOf(self.menu[a].id) > 0) {
self.menusIds.splice(self.menusIds.indexOf(self.menu[a].id), 1);
}
}
} else {
if (self.menusIds.indexOf(self.menu[a].id) > -1) {
self.menu[a].children.map(item => {
if (self.menusIds.findIndex((n) => n == item.id) < 0) {
self.menusIds.push(item.id)
}
})
} else {
self.menu[a].children.map(item => {
if (self.menusIds.findIndex((n) => n == item.id) > -1) {
self.menusIds.splice(self.menusIds.findIndex((n) => n == item.id), 1);
}
})
}
}
}
4.已有選擇記錄的復現
第三小部分已經說得很清楚了,復現已選擇的記錄,只要把已選的id放進menusIds,就能實現選中和未選中狀態的復現了。
this.menusIds = params.ids;
演示項目
最後給出一個演示的demo項目,項目結構比較簡單,注意如果有chrome打開,本地請求json數據會出現跨域的問題,建議採用firefox打開。
點此查看項目