自定义排序组件

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

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

相关推荐
logstach30 分钟前
QML-Grid和OpacityMask
前端·qml
C+ 安口木1 小时前
前端代码规范 - 日志打印规范
前端·代码规范
朝阳391 小时前
js【最佳实践】遍历数组的八种方法(含数组遍历 API 的对比)for,forEach,for of,map,filter,reduce,every,some
javascript
Jesse_Kyrie1 小时前
配置windows环境下独立浏览器爬虫方案【不依赖系统环境与chrome】
前端·chrome·爬虫·python·scrapy
野槐3 小时前
CSS原子化
前端·css
#学习的路上3 小时前
Bean的管理
java·前端·数据库
香蕉麻花皮3 小时前
vue3 滚动条滑动到元素位置时,元素加载
前端·javascript·vue.js
Fipped3 小时前
Node.js迈向后端世界:从"Hello World"到"Hello Backend!"
前端
2401_857638033 小时前
【Perl CGI脚本全解析】打造动态Web应用的秘籍
前端·scala·perl
Delighted3 小时前
百度面试题:输入框的防抖节流
前端·javascript