自定义排序组件

自定义排序组件,实现了与Form表单的完美集成,支持升序、降序以及不排序三种状态的灵活切换。即提高了表单的交互性,又在现有UI框架基础上扩展自定义功能,满足特定业务需求。

需求:要在 Form 表单中实现排序组件功能,类似 Table 中的排序组件,没有现成的组件,只能自己写。

1. Form 表单结合排序组件

(1)Form 表单逻辑:

tsx 复制代码
// 创建 Form 实例,用于管理所有数据状态
const [form] = Form.useForm();
// 定义排序逻辑
const [subjectOrder, setSubjectOrder] = useState("none");

// 字段值更新时触发回调事件
const onValuesChange = (values: any, allValues: any) => {
  console.log("form: ", values, allValues);
};

<Form form={form} onValuesChange={onValuesChange} layout="inline">
  <Form.Item name="subjectOrder" valuePropName="checked">
    <Checkbox
      onChange={(e) => setSubjectOrder(e.target.checked ? "asc" : "desc")}
    >
      <CustomSorter label="学科" type={subjectOrder} />
    </Checkbox>
  </Form.Item>
</Form>;

注意:Form.Item 中使用 Checkbox 组件时,需要配置valuePropName="checked",不然会提示警告信息:

Warning: [antd: Checkbox] value is not a valid prop, do you mean checked?

官网也有说明:valuePropName为子节点的值的属性。Switch、Checkbox 的 valuePropName 应该是 checked,否则无法获取这个两个组件的值。该属性为 getValueProps 的封装,自定义 getValueProps 后会失效

具体可查看官网demo:Form表单

(2)自定义 CustomSorter 组件逻辑:

tsx 复制代码
import { CaretUpOutlined, CaretDownOutlined } from "@ant-design/icons";
import "./index.scss";

interface iProps {
  label: string;
  type: string; // none-不排序;asc-升序;desc-降序
}

const CustomSorter = (props: iProps) => {
  const { label, type = "none" } = props;
  return (
    <div className="custom-sorter">
      <div className="label">{label}</div>
      <div className="sorter">
        <CaretUpOutlined className={type === "asc" ? "active" : ""} />
        <CaretDownOutlined className={type === "desc" ? "active" : ""} />
      </div>
    </div>
  );
};

export default CustomSorter;

最初的想法是通过Checkbox组件的状态控制升序、降序,然后再隐藏多选框,就能实现业务需求了。

效果如下图所示:

缺点:只能控制两种状态切换(asc-升序;desc-降序),无法切换回原始状态(none不排序状态),而且封装不彻底,Checkbox 无法放到 CustomSorter里面去,移到里面去之后,Checkbox 就不受 Form 表单控制了,还需要调整代码才行,导致状态管理复杂,搞得更麻烦了。最终决定自己实现,不借助 Checkbox了。

2. 自定义排序组件

要想实现三种状态的切换,需要自定义排序组件。而且还要和 Form 表单联动,即受控于 Form 表单。

自定义或第三方的表单控件,也可以与 Form 组件一起使用。只要该组件遵循以下的约定:

  • 提供受控属性 value 或其它与 valuePropName 的值同名的属性。
  • 提供 onChange 事件或 trigger 的值同名的事件。

自定义 CustomSorter 组件逻辑,如下所示:

tsx 复制代码
interface iProps {
  label: string; // 标签文本
  value?: string; // 当前排序状态值 none-不排序;asc-升序;desc-降序
  onChange?: (value: string) => void; // 排序状态变更回调 
}

const CustomSorter = (props: iProps) => {
  const { label, value = "none", onChange } = props;
  const [order, setOrder] = useState(value);

  const handleChange = () => {
    // 通过三元运算符精炼地实现状态循环切换逻辑
    const val = order === "none" ? "asc" : order === "asc" ? "desc" : "none";
    setOrder(val);
    if (onChange) {
      onChange(val);
    }
  };

  return (
    <div className="custom-sorter" onClick={handleChange}>
      <div className="label">{label}</div>
      <div className="sorter">
        <CaretUpOutlined className={order === "asc" ? "active" : ""} />
        <CaretDownOutlined className={order === "desc" ? "active" : ""} />
      </div>
    </div>
  );
};

export default CustomSorter;

样式文件 index.scss 如下所示:

scss 复制代码
.custom-sorter {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  .sorter {
    display: flex;
    flex-direction: column;
    color: #ddd;

    .active {
      color: #1d52a9;
    }
    .anticon {
      margin-left: 5px;
      font-size: 12px;
      position: relative;
    }
    .anticon-caret-up {
      top: 2px;
    }
    .anticon-caret-down {
      top: -2px;
    }
  }
}

最终实现效果,如下所示:

相关推荐
FreeCultureBoy31 分钟前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom1 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom1 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom1 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom1 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom2 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试
LaoZhangAI2 小时前
2025最全GPT-4o图像生成API指南:官方接口配置+15个实用提示词【保姆级教程】
前端
ONE_Gua2 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫
LaoZhangAI3 小时前
2025最全Cherry Studio使用MCP指南:8种强大工具配置方法与实战案例
前端
咖啡教室3 小时前
前端开发日常工作每日记录笔记(2019至2024合集)
前端·javascript