《Element UI 级联选择器深度定制:打造省单选、市县多选的地区权限授权组件》

127 阅读4分钟

前言

在企业级应用开发中,地区权限授权是一个常见的需求。为了简化用户操作,我们往往会使用级联选择器来展示地区数据。Element UI 提供的 el-cascader 和 el-cascader-panel 组件可以帮助我们快速实现级联选择功能。 然而,在实际业务中,我们可能会遇到更复杂的场景,例如:省一级单选,市、县多选。Element UI 组件默认是多选的, 这就需要我们进行深度定制。本文将基于 el-cascader-panel 组件,结合业务需求,分享如何实现一个省一级单选、市、县多选的地区权限授权组件,并剖析核心代码逻辑。

需求分析

我们的目标是开发一个用于地区权限授权的组件,主要需求如下: 省份: 省级只能单选,用户只能选择一个省份。 市、县: 市级和县级可以选择多个,用户可以选择一个省下的多个市和县。 数据回显: 组件可以根据已有的数据,回显选中的省、市、县信息。 参数处理: 需要处理后端要求的复杂参数格式。 为了简化文章,我们暂时不关注后端参数的细节处理,重点放在如何实现一级单选,二三级多选,并理解其核心代码。

组件实现

我们选择 el-cascader-panel 作为基础组件,因为它更灵活,可以自定义更多细节。下面是组件的基本结构:

<template>
  <el-cascader-panel
    ref="regionCascader"
    :options="regionCityData"
    :props="regionProps"
    @change="handleChange"
    v-model="checkedRegion"
    placeholder="所属地区"
    clearable
  ></el-cascader-panel>
</template>

这里,我们使用了 el-cascader-panel 组件,并绑定了以下属性: options: 用于展示的地区数据,类型是数组。 props: 配置项,用于指定数据中 label、value 和 children 属性的 key 值,并且配置 multiple 为 true。 @change: 监听选择变化的事件,核心逻辑在这里实现。 v-model: 双向绑定选中的数据。 placeholder 和 clearable:占位符和清除按钮。 核心代码解析 现在,让我们来深入分析实现一级单选、二三级多选的核心代码 handleChange 方法:

import regionSeatLibs from "@/utils/regionsSeatLibs.js";
import { deepClone } from "@/utils/index"; // 确保 deepClone 正确引入

export default {
  data() {
    return {
      dialogWidth: "635px",
      checkedRegion: [], // 选中的集合
      cascaderTag: [], // 旧集合, 用于辅助判断一级单选
      regionProps: {
        label: "n",
        value: "i",
        children: "c",
        multiple: true, // 启用多选
      },
      regionCityData: regionSeatLibs[0].c, // 初始化的城市数据
      visible: false,
    };
  },
methods: {
    /**
     * @Description: 处理省单选问题
     * @Author: zhangyantao
     * @Date: 2025-01-23 17:07:55
     * @LastEditTime:
     * @LastEditors: zhangyantao
     * @param {*} val
     */
    handleChange(val) {
      if (val && val.length > 0) {
        // 初次选择,初始化 casaderTag
        if (this.cascaderTag.length == 0) {
          this.cascaderTag = deepClone(val);
          this.checkedRegion = this.cascaderTag;
        } else {
          // 获取 casaderTag 中一级节点的数据
          const id = this.cascaderTag[0][0];
          // 判断当前选择项是否是同级下的数据, 如果不是, 则过滤掉
          if (
            !val.every((i) => {
              return i[0] == id;
            })
          ) {
            this.checkedRegion = val.filter((el) => {
              return el[0] != id;
            });
          }
        }
        // 同步 casaderTag 数据
        this.cascaderTag = this.checkedRegion;
      } else {
        // 清空
        this.cascaderTag = [];
      }
    },
  },
};

这个 handleChange 方法的核心逻辑如下:

  1. 判断 val 是否存在:
  2. val 是 el-cascader-panel 传递过来的参数,代表当前选中的所有节点数据
  3. 如果 val 不存在,或者为空数组,说明是清除操作, 直接清空 cascaderTag
  4. 初次选择判断:
  5. 通过 this.cascaderTag.length == 0 判断是否是第一次选择。
  6. 如果是第一次选择,直接将 val 赋值给 cascaderTag 和 checkedRegion 。cascaderTag 用于辅助判断一级单选, checkedRegion 用于双向绑定 el-cascader-panel 组件。
  7. 非初次选择判断:
  8. 获取 cascaderTag 中一级节点的数据 const id = this.cascaderTag[0][0]。
  9. 使用 every 方法判断, 如果新选中的节点,有一项不是第一级节点下的,就使用 filter 方法,过滤掉其他的一级节点数据。 filter 方法保留了和第一级节点相同的数据,也就实现了第二级和第三级的多选功能。
  10. 同步数据:
  11. 将 checkedRegion 赋值给 cascaderTag, 保持数据同步。
  12. regionSeatLibs 是用于维护地区数据的工具类。
  13. deepClone 是深拷贝工具函数,确保赋值的时候不会相互影响。
  • multiple 属性设置为 true, 可以开启 el-cascader-panel 的多选功能。
  • cascaderTag 用于辅助判断, 并保留了上次选择的一级数据。
  • checkedRegion 用于存储当前所有选中的数据, 用于双向绑定 el-cascader-panel 组件。

这段代码主要利用了 el-cascader-panel 的 change 事件, 通过 cascaderTag 辅助判断, 实现了省一级单选,市、县多选。

总结 本文通过一个实际的业务场景,分享了如何基于 el-cascader-panel 组件,实现一个省一级单选、市、县多选的地区权限授权组件。核心在于 handleChange 方法的实现,它通过维护一个 cascaderTag 变量来辅助判断,保证了省一级只能单选,市、县可以多选。

通过本次实践,我们掌握了以下关键知识点:

el-cascader-panel 组件的使用。 利用 change 事件进行自定义逻辑处理。 通过维护辅助变量来实现复杂的单选/多选需求。 希望本文能为你提供一些思路,帮助你在实际开发中更好地应用 Element UI 组件。如果你有任何问题,欢迎在评论区交流。