Skip to content

嵌套多选框

template

vue
<template>
    <div class="multi-check" :style="{ width: width }">
      <div class="multi-check-item" v-if="isCheckAll">
        <el-checkbox
          :indeterminate="isIndeterminate"
          v-model="checkAll"
          @change="handlerChange(0,null,$event)"
          >全选{{ totalLabel }}</el-checkbox
        >
      </div>
      <div class="multi-check-item" v-for="item in dataList" :key="item.code">
        <el-checkbox
          v-model="item.isChecked"
          :indeterminate="item.indeterminate"
          :label="item.code"
          :value="item.value"
          @change="handlerChange(1, item, $event)"
        >
          {{ item.label }}
        </el-checkbox>
        <div class="multi-check-item">
          <el-checkbox
            v-model="child.isChecked"
            @change="handlerChange(2, item, $event)"
            v-for="child in item.children || []"
            :key="child.code"
            :label="child.value"
          >
            {{ child.label }}
          </el-checkbox>
        </div>
      </div>
    </div>
</template>

JS

vue
<script>
export default {
  name: "multiCheckList",
  //传入三个参数 是否全选 数据数组 宽度
  props: {
    isCheckAll: {
      type: Boolean,
      default: false,
    },
    dataList: {
      type: Array,
      required: true,//必须传入
    },
    width: {
      type: String,
      default: "100%",
    },
  },
  data() {
    return {
      checkAll: false,//是否权限
      isIndeterminate: false,//全选按钮样式
      totalLabel: "", //总计标签
    };
  },
  watch: {
    dataList: {
      handler() {
        const isChangeSum = this.dataList.reduce((prev, cur) => {
          return prev + (cur.isChange || 0);
        }, 0); //计算改变的个数
        const isCheckSum = this.dataList.reduce((prev, cur) => {
          return prev + (cur.isChecked || 0);
        }, 0); //统计选择的次数
        this.checkAll = isCheckSum && isCheckSum === this.dataList.length;
        this.isIndeterminate = !!isChangeSum; //!!转换为Boolean值
        if (isCheckSum && isCheckSum === this.dataList.length) {
          this.isIndeterminate = false;
        }
        this.totalLabel =
          isChangeSum === 0 ? "" : `已选择(${isChangeSum})个分类`;
      },
      immediate: true,
      deep: true,
    },
  },
  computed: {
    getDataList() {
      //获取DataList内父级和子级被选中
      let parentList = [];
      let childList = [];
      this.dataList.forEach((item) => {
        if (item.isChecked) parentList.push(item.value);
        (item.children || []).forEach((child) => {
          if (child.isChecked) {
            childList.push(child.value);
          }
        });
      });
      return [parentList, childList];
    },
  },
  methods: {
    //控制全选 通过遍历的方法 给每一级设置是否选中和是否改变
    handlerCheckAll(isChecked) {
      this.dataList.forEach((item) => {
        this.$set(item, "isChecked", isChecked);
        this.$set(item, "isChange", isChecked);
        if (isChecked) this.$set(item, "isIndeterminate", false);
        //子级在遍历设置选中
        item.children.forEach((child) => {
          this.$set(child, "isChecked", isChecked);
        });
      });
    },
    handlerChange($type, $row, $event) {
      //判断是否选中
      let isChecked = !$event.target ? $event : $event.target.checked;
      if ($type === 0) {
        //全选
        this.handlerCheckAll(isChecked);
        this.$emit("change", this.getDataList[0], this.getDataList[1]);
        return;
      }
      if ($type === 1) {
        $row.children.forEach((item) => {
          this.$set(item, "isChecked", isChecked);
        });
      }
      const checkCount = $row.children.reduce((prev, cur) => {
        let check = 0;
        if (cur.isChecked === undefined) {
          check = 0;
        } else {
          check = +cur.isChecked;
        }
        return prev + +check;
      }, 0); //统计选择的次数
      this.$set($row, "isChange", checkCount === 0 ? false : true);
      this.$set(
        $row,
        "isChecked",
        checkCount && checkCount === $row.children.length ? true : false
      );
      this.$set(
        $row,
        "isIndeterminate",
        checkCount && checkCount < $row.children.length ? true : false
      );

      this.$emit("change", this.getDataList[0], this.getDataList[1]);
    },
  },
};
</script>

使用

vue
 <multi-check-list :dataList="dataList" :isCheckAll="true" @change="handlerDataCheck"/>
/*
  data(){
    return{
      dataList:[{
           code:1001,
           label:'电商',
           value:'a001',
           children:[{
             code:1002,
             label:'淘宝',
             value:'a002'
           }, {
             code:1003,
             label:'京东',
             value:'a003'
           }, {
             code:1004,
             label:'亚马逊',
             value:'a002'
           }]
         }, {
           code:1005,
           label:'生活服务',
           value:'a005',
           children:[{
             code:1006,
             label:'美团',
             value:'a006'
           }, {
             code:1007,
             label:'大众点评',
             value:'a007'
           }, {
             code:1008,
             label:'滴滴',
             value:'a008'
           }, {
             code:1009,
             label:'饿了么',
             value:'a009'
           }]
         }],
    }
  },
*/