前端实现具有依赖关系的多个级联选择器

背景

  • 使用的antd-design级联选择器[Cascader](https://ant-design.antgroup.com/components/cascader-cn)
  • 根据数据映射出级联选择器,但是有的级联选择器要看她的依赖值有没有被选择,选择后才会显示

比如没选择前:

选择后显示:

方案

js 复制代码
      group_code: "A", // 树选择框的code
      group_desc: "测试A", // 树选择框的中文
      placeholder: "测试A", // 树选择框的提示
      dependencse: [], // 树选择框的依赖性决定是否要现实
      group_options: [ //树选择框的具体值
        { //antd design常用结构
          label: "A1", 
          value: "A1",
          children: [],
        },
      ],
    },

1. 导入依赖

javascript 复制代码
import { useState } from "react";
import { Cascader } from "antd";
  • useState 是 React 的一个 Hook,用于在函数组件中管理状态。
  • Cascader 是 Ant Design 提供的级联选择器组件,支持多级联动选择。

2. 组件定义

javascript 复制代码
const MultipleCascader = ({
  multipleCascaderOption,
  selectValues,
  setSelectValues,
}) => {
  • MultipleCascader 是一个函数组件,接收三个 props:
    • multipleCascaderOption:包含级联选择器的配置选项。
    • selectValues:当前已选中的值。
    • setSelectValues:用于更新已选中值的函数。

3. 解构 props

javascript 复制代码
const {
  group_options: options,
  placeholder,
  group_desc,
  group_code,
  dependencse,
} = multipleCascaderOption;
  • multipleCascaderOption 中解构出以下属性:
    • options:级联选择器的选项数据。
    • placeholder:选择器的占位符文本。
    • group_desc:组的描述信息。
    • group_code:组的唯一标识符。
    • dependencse:依赖关系,表示当前选择器是否依赖于其他选择器的选择结果。

4. 状态管理

javascript 复制代码
const [value, setValue] = useState();
  • value 用于存储当前选择器的选中值。
  • setValue 是更新 value 的函数。

5. handleDisabled 函数

javascript 复制代码
const handleDisabled = (extraLogic) => {
  const values = selectValues.filter(
    (option) => option.group_code !== group_code
  );

  values
    .filter((option) =>
      option.dependencse.some((opt) => opt.startsWith(group_code))
    )
    .forEach((option) =>
      extraLogic ? (option.is_disabled = extraLogic(option)) : true
    );
  return values;
};
  • 该函数用于处理依赖关系,禁用或启用其他选择器。
  • extraLogic 是一个可选的回调函数,用于自定义禁用逻辑。
  • 首先过滤掉当前选择器的值,然后根据依赖关系禁用或启用其他选择器。

6. onChange 函数

javascript 复制代码
const onChange = (selectRows, selectedOptions) => {
  let rows = selectRows,
    values;
  if (selectRows.length === 0) {
    values = handleDisabled();
  } else {
    const group = selectRows[selectRows.length - 1][0];
    rows = selectRows.filter((item) => item[0] === group);
    const secondLevelMenus = selectRows.map((item) => item[1]);
    const children = selectedOptions[selectedOptions.length - 1][0].children;
    const value = rows[0][0];
    const key = `${group_code}-${value}`;
    const sameValue = selectValues.find((option) => option.key === key);

    values = [
      ...handleDisabled((option) => !option.dependencse.includes(key)),
      {
        ...sameValue,
        key,
        group_code,
        group_desc,
        value,
        reasons: children.filter(({ value }) =>
          secondLevelMenus.includes(String(value))
        ),
        dependencse,
        is_disabled: false,
      },
    ];
  }
  setValue(rows);
  setSelectValues(values);
};
  • 该函数在用户选择选项时触发。
  • 根据用户的选择更新 valueselectValues
  • 如果用户清空了选择,调用 handleDisabled 函数处理依赖关系。
  • 如果用户选择了选项,更新 selectValues 并处理依赖关系。

7. showCascader 函数

javascript 复制代码
const showCascader = () => {
  if (dependencse.length === 0) {
    return true;
  }
  return dependencse.some((option) =>
    selectValues.some(({ key }) => key === option)
  );
};
  • 该函数用于判断是否显示当前级联选择器。
  • 如果没有依赖关系(dependent 为空),则显示选择器。
  • 如果有依赖关系,则检查依赖的选择器是否有选中值,如果有则显示当前选择器。

8. 渲染逻辑

javascript 复制代码
if (showCascader()) {
  return (
    <Cascader
      multiple
      value={value}
      style={{ minWidth: 140, marginRight: 20 }}
      showCheckedStrategy={Cascader.SHOW_CHILD}
      placeholder={placeholder}
      maxTagCount={1}
      expandTrigger="hover"
      options={options}
      onChange={onChange}
    />
  );
}
return <></>;
  • 根据 showCascader 的返回值决定是否渲染 Cascader 组件。
  • 如果返回 true,则渲染 Cascader 组件,并传入相关属性。
  • 如果返回 false,则返回空片段 <> </>,不渲染任何内容。

测试地址 codesandbox.io/p/sandbox/m...

相关推荐
强强学习1 小时前
HTML5 起步
前端·html·html5
念九_ysl3 小时前
前端循环全解析:JS/ES/TS 循环写法与实战示例
前端·javascript·typescript
anyup_前端梦工厂5 小时前
了解几个 HTML 标签属性,实现优化页面加载性能
前端·html
前端御书房5 小时前
前端PDF转图片技术调研实战指南:从踩坑到高可用方案的深度解析
前端·javascript
2301_789169545 小时前
angular中使用animation.css实现翻转展示卡片正反两面效果
前端·css·angular.js
风口上的猪20156 小时前
thingboard告警信息格式美化
java·服务器·前端
程序员黄同学7 小时前
请谈谈 Vue 中的响应式原理,如何实现?
前端·javascript·vue.js
爱编程的小庄7 小时前
web网络安全:SQL 注入攻击
前端·sql·web安全
宁波阿成8 小时前
vue3里组件的v-model:value与v-model的区别
前端·javascript·vue.js
柯腾啊8 小时前
VSCode 中使用 Snippets 设置常用代码块
开发语言·前端·javascript·ide·vscode·编辑器·代码片段