element-ui的el-checkbox實現嵌套多選,單選

前言

前段時間做一個vue項目過程中遇到element-ui的el-checkbox循環嵌套的問題,後參考網上的文章加之自己的修改,現做一個記錄分享。我這裏僅僅是以一個二級菜單爲例,三級菜單也可以做相應的修改。

最終效果圖

在這裏插入圖片描述

主要需求

  1. 實現多選框層級嵌套
  2. 當選中一個二級子菜單的時候,其對應的上級菜單也選中
  3. 若二級子菜單無一個選中,則對應的一級菜單也不是選中狀態
  4. 當一級菜單發生點擊事件時,若原本爲選中狀態,則取消選中,若該菜單下有二級子菜單,所有子菜單也取消選中狀態;若原本爲未選中狀態,則改爲選中狀態,若該菜單下有二級子菜單,所有子菜單也改爲選中狀態。
  5. 實現已有的選擇記錄的復現。

實現過程

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打開。
點此查看項目

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章