让 ElementUI 级联选择器更易用:限制最大选择数量

实现思路

利用 slot-scope 功能自定义节点内容,我们在 template 内加入一个具有 exceeded-overlay 类的遮罩元素,并为其定义一个点击事件来提示超出最大限制。当选中数量未达到最大限制时,遮罩元素将保持隐藏;若超过限制,则显示。但这样做有一个问题:在达到最大限制后,点击已选中的节点仍会弹出“超出最大限制”的错误提示。

为解决此问题,我们需要隐藏已选中节点的遮罩元素。巧妙运用 CSS 技巧,我们能够实现这一需求,确保在各种场景下都能正常使用。

代码片段

代码实现

<template>
  <el-cascader
    v-model="selectedLocations"
    :options="locationOptions"
    popper-class="location"
    placeholder="期望工作地区"
    filterable
    :props="cascaderProps"
    :show-all-levels="false"
  >
    <template slot-scope="{ data }">
      {
   
   { data.label }}
      <span
        v-if="selectedLocations.length >= 2"
        class="exceeded-overlay"
        @click="handleSelectionExceeded"
      ></span>
    </template>
  </el-cascader>
</template>

<script>
export default {
      
      
  data() {
      
      
    return {
      
      
      cascaderProps: {
      
      
        multiple: true,
        expandTrigger: 'hover',
        checkStrictly: true
      },
      selectedLocations: [],
      locationOptions: [
        {
      
       value: 1002, label: "北京" },
        {
      
       value: 1024, label: "上海" },
        {
      
      
          value: 1001,
          label: "安徽",
          children: [
            {
      
       value: 100106, label: "合肥" },
            {
      
       value: 100114, label: "芜湖" },
            {
      
       value: 100101, label: "蚌埠" }
          ]
        },
        {
      
      
          value: 1003,
          label: "福建",
          children: [
            {
      
       value: 100300, label: "福州" },
            {
      
       value: 100307, label: "厦门" },
            {
      
       value: 100306, label: "三明" },
            {
      
       value: 100305, label: "泉州" },
            {
      
       value: 100301, label: "龙岩" }
          ]
        }
      ]
    }
  },

  methods: {
      
      
    handleSelectionExceeded() {
      
      
      this.$message.error('最多只能选择2个')
    }
  }
}
</script>

<style lang="scss">
.location {
      
      
  /* 遮罩元素-覆盖整个li元素 */
  .exceeded-overlay {
      
      
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    z-index: 20;
  }
  
  /* 选中节点隐藏遮罩元素 */
  .el-checkbox.is-checked ~ .el-cascader-node__label {
      
      
    .exceeded-overlay {
      
      
      display: none;
    }
  }
}
</style>

watch 的实现方案

实际上,通过使用 watch 来监听选中值也是可行的。当选中数量超过最大限制时,我们可以将选中值恢复到原始状态。这种方法简洁明了,逻辑清晰且易于理解。但是,它带来了一个副作用:一旦超过最大限制,级联选择器会自动跳回至 options 数组的第一个位置,并且脱离用户当前选中的位置。我并不喜欢这样的体验。

ElCascader-Max1.gif

这种方式会打扰用户当前操作,体验上似乎不是很友好

<template>
  <el-cascader
    v-model="selectedLocations"
    popper-class="location"
    placeholder="期望工作地区"
    filterable
    :props="{ multiple: true, expandTrigger: 'hover', checkStrictly: true }"
    :show-all-levels="false"
    :options="locationOptions"
    @change="handleLocationChange"
  >
</el-cascader>
</template>

<script>
export default {
      
      
  data() {
      
      
    return {
      
      
      selectedLocations: [], // 保存用户选择的地区信息
      locationOptions: [ // 包含所有可选的地区数据对象
        {
      
       value: 1002, label: "北京" },
        {
      
       value: 1024, label: "上海" },
        {
      
      
          value: 1001,
          label: "安徽",
          children: [
            {
      
       value: 100106, label: "合肥" },
            {
      
       value: 100114, label: "芜湖" },
            {
      
       value: 100101, label: "蚌埠" }
          ]
        },
        {
      
      
          value: 1003,
          label: "福建",
          children: [
            {
      
       value: 100300, label: "福州" },
            {
      
       value: 100307, label: "厦门" },
            {
      
       value: 100306, label: "三明" },
            {
      
       value: 100305, label: "泉州" },
            {
      
       value: 100301, label: "龙岩" }
          ]
        }
      ]
    }
  },

  watch: {
      
      
    // 期望工作地区,最多允许选择2个
    selectedLocations: function (val, oldVal) {
      
      
      if (val.length > 2) {
      
      
        this.$message.error('最多可选2个')
        this.$nextTick(() => (this.selectedLocations = oldVal))
      }
    }
  }
}
</script>

猜你喜欢

转载自blog.csdn.net/qq_34626094/article/details/130516784