自定义排序组件

自定义排序组件,实现了与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;
    }
  }
}

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

相关推荐
晴空万里藏片云1 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
曦月合一1 小时前
html中iframe标签 隐藏滚动条
前端·html·iframe
奶球不是球1 小时前
el-button按钮的loading状态设置
前端·javascript
kidding7231 小时前
前端VUE3的面试题
前端·typescript·compositionapi·fragment·teleport·suspense
无责任此方_修行中2 小时前
每周见闻分享:杂谈AI取代程序员
javascript·资讯
Σίσυφος19003 小时前
halcon 条形码、二维码识别、opencv识别
前端·数据库
学代码的小前端3 小时前
0基础学前端-----CSS DAY13
前端·css
dorabighead4 小时前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
css趣多多4 小时前
案例自定义tabBar
前端
姑苏洛言6 小时前
DeepSeek写微信转盘小程序需求文档,这不比产品经理强?
前端