el-cascader 支持多层级,多选(可自定义限制数量),保留最后一级

发布于:2024-06-19 ⋅ 阅读:(189) ⋅ 点赞:(0)

多功能的 el-cascader

序言:最近遇到一个需求关于级联的,有点东西,这里是要获取某个产品类型下的产品,会存在产品类型和产品在同一级的情况,但是产品类型不能勾选;

  • 情况1(二级菜单是产品)
    在这里插入图片描述
  • 情况2(二级菜单也有可能是产品类型,三级是产品)
    在这里插入图片描述

需求如下:

  1. 支持多选且保留最后勾选项(不包含父级)
  2. 自定义限制勾选数量(这里最多3个)
  3. 层级不固定,有子级的才可以点击
  4. 父级不能勾选
  5. 返回给后端的参数需要将最后勾选的子级的lable和value值转为字符串以逗号分隔

实现方式

  1. 支持多选可用:props="{ checkStrictly: true, label: 'name', emitPath: false, multiple: true }" multiple: true 实现;
    不包含父级: :show-all-levels="false"

  2. 限制数量这个就比较有趣了,因为官网上的limit在这里没有用,所以得自己去写,需要在数量超过3个的时候 再点下一个的时候替换掉上次勾选那个,3个以下就直接拿数据就行,因为勾选层级不固定,可以选不同层级的,所以需要用递归去获取勾选的值,下面是数据结构:
    在这里插入图片描述

  3. 递归获取label值(最多3个,可修改):
    mainProductName:lable值 (字符串)
    mainProductOptions:级联的数据源
    findObjectsByKey:扁平化数组
    mainProductArr:value (数组字符串) 用来编辑时回显 很重要

    mainProductChange(val) {
      const textArr = [];
      if (val.length > 3) {
        val.splice(-2, 1);
        for (let i = 0; i < val.length; i++) {
          let itemValue = findObjectsByKey(this.mainProductOptions, 'id', val[i]);
          textArr.push(itemValue.name);
        }
        this.formData.mainProductName = textArr.join(',');
        this.$message.warning('最多只能选择三种产品');
        return val;
      } else {
        for (let i = 0; i < val.length; i++) {
          let itemValue = findObjectsByKey(this.mainProductOptions, 'id', val[i]);
          textArr.push(itemValue.name);
        }
        this.formData.mainProductName = textArr.join(',');
      }
      this.formData.mainProductArr = val;
    },
    
    //查找多层数组中的符合条件的item
    //arr 被查找的数组  key 查找的key  keyValue 查找的值
    export function findObjectsByKey(arr, key, keyValue) {
      //先把数组扁平化
      function flatten(arr, newarr) {
        //遍历arr数组
        for (var i = 0; i < arr.length; i++) {
          if (arr[i].children instanceof Array) {
            flatten(arr[i].children, newarr);
          } else {
            newarr.push(arr[i]);
          }
        }
        //返回新数组
        return newarr;
      }
      let newArr = flatten(arr, []);
      let itemValue = {};
      for (let item of newArr) {
        if (item[key] == keyValue) {
          itemValue = item;
          return itemValue;
        }
      }
      return itemValue;
    }
    
  4. 不能勾选是产品类型的父级(这里就需要对数据源做个处理),给是产品类型的数据加上 disabled,这时候就需要一个字段来判断了,后端配合一下,我这里用的是(isVariety)方法如下:

     traverseArray(arr) {
          arr.forEach(item => {
            item.disabled = item.isVariety == 0 ? true : false;
            item.value = item.id;
            if (item.children && item.children.length > 0) {
              this.traverseArray(item.children);
            }
          });
        },
    

    为了不修改源数据,所以用一个变量暂存一下

    getIndustryVarietyList({ isVariety: '' }).then(res => {
    	        if (res.data.data.length > 0) {
    	          let temp = res.data.data;
    	          this.traverseArray(temp);
    	          this.mainProductOptions = temp;
    	        }
    	      });
    
  5. 级联代码如下:

 <el-form-item label="主营产品:" prop="mainProductArr">
      <el-cascader
         ref="cascaderArr"
            style="width: 100%"
             v-model="formData.mainProductArr"
             :options="mainProductOptions"
              show-all-levels="false"
              placeholder="最多选择三种产品"
              clearable
              @change="mainProductChange"
              :props="{ checkStrictly: true, label: 'name', emitPath: false, multiple: true }"
                ></el-cascader>
              </el-form-item>
  1. 最后源码
	<template>
	  <div>
	    <el-form :model="formData" label-width="120px" :rules="formRules" ref="formData">
	      <el-col :span="10">
	        <el-form-item label="主营产品:" prop="mainProductArr">
	          <el-cascader
	            ref="cascaderArr"
	            style="width: 100%"
	            v-model="formData.mainProductArr"
	            :options="mainProductOptions"
	            :show-all-levels="false"
	            placeholder="最多选择三种产品"
	            clearable
	            @change="mainProductChange"
	            :props="{ checkStrictly: true, label: 'name', emitPath: false, multiple: true }"
	          ></el-cascader>
	        </el-form-item>
	      </el-col>
	    </el-form>
	  </div>
	</template>
	<script>
	export default {
	  data() {
	    return {
	      mainProductOptions: [],
	      // 表单数据
	      formData: {
	        mainProduct: '',
	        mainProductArr: [],
	        mainProductName: '',
	      },
	    };
	  },
	  created() {},
	  watch: {},
	  mounted() {
	    getIndustryVarietyList({ isVariety: '' }).then(res => {
	      if (res.data.data.length > 0) {
	        let temp = res.data.data;
	        this.traverseArray(temp);
	        this.mainProductOptions = temp;
	      }
	    });
	  },
	  methods: {
	    mainProductChange(val) {
	      const textArr = [];
	      if (val.length > 3) {
	        val.splice(-2, 1);
	        for (let i = 0; i < val.length; i++) {
	          let itemValue = findObjectsByKey(this.mainProductOptions, 'id', val[i]);
	          textArr.push(itemValue.name);
	        }
	        this.formData.mainProductName = textArr.join(',');
	        this.$message.warning('最多只能选择三种产品');
	        return val;
	      } else {
	        for (let i = 0; i < val.length; i++) {
	          let itemValue = findObjectsByKey(this.mainProductOptions, 'id', val[i]);
	          textArr.push(itemValue.name);
	        }
	        this.formData.mainProductName = textArr.join(',');
	      }
	      this.formData.mainProductArr = val;
	    },
	    traverseArray(arr) {
	      arr.forEach(item => {
	        item.disabled = item.isVariety == 0 ? true : false;
	        item.value = item.id;
	        if (item.children && item.children.length > 0) {
	          this.traverseArray(item.children);
	        }
	      });
	    },
	  },
	};

还有个不足就是不能把含有children的勾选框给去掉,有知道的大佬告诉教教我

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到