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

背景

  • 使用的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...

相关推荐
s11show_16325 分钟前
hz修改后台新增keyword功能
android·java·前端
二个半engineer32 分钟前
Web常见攻击方式及防御措施
前端
co松柏39 分钟前
程序员必备——AI 画技术图技巧
前端·后端·ai编程
前端大白话43 分钟前
前端人速码!10个TypeScript神仙技巧,看完直接拿捏项目实战
前端·javascript·typescript
五号厂房43 分钟前
React 异步回调中产生的闭包问题剖析及解决
前端
用户2031196600961 小时前
GeometryProxy 和 GeometryReader 的区别
前端
前端大白话1 小时前
前端必看!10个React实战技巧让你代码起飞,附超详细注释
前端·javascript·react.js
bigyoung1 小时前
使用 Arco Design 的 Table 组件实现可编辑列
前端·react.js·arco design
前端大白话1 小时前
前端必学!10 个超实用 Vue3 实战技巧大放送
前端·javascript·vue.js
谦谦橘子1 小时前
手写react-router,理解react-router原理
前端·javascript·react.js