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.点击事件的处理

  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打开。
点此查看项目

  • 8
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值