React - 实现一个基于 Antd 的数值范围组件

简介: 这篇文章介绍了如何实现一个基于Ant Design的数值范围组件,以满足数据采集流程中表单数据的录入需求。文章详细说明了组件的设计思路、代码结构、使用方式以及参数说明,并提供了效果预览和注意事项。组件支持只能输入数字,具有自定义表单控件封装的特点,同时支持所有InputNumber属性,以适应不同业务场景的需求。

前言

最近公司的产品需求要做一个数据采集流程,这个流程里面有比较多的表单数据,其中有一个输入数值范围的控件,这个功能还是很常见的,但是之前的开发没有封装成一个公共组件,特此自己造轮子。

需求原型

image.png

使用场景

当需求中需要录入数值范围的表单数据

实现思路

考虑到组件的共用性和拓展性,它应具备以下功能:

  1. 只能输入数字,选择 InputNumber 数字输入框,并继承该组件的所有API属性

  2. 当最小值大于最大值,或者最大值小于最小值时,应调换位置

  3. 基于 自定义表单控件 封装

代码结构

由于这个功能实现还是比较简单的,组件的细节便不多描述,直接上代码:

import { Col, InputNumber, Row } from 'antd'
import type { InputNumberProps } from 'antd/es/input-number'
import { gt, toNumber } from 'lodash'
import React, { FC, FocusEventHandler } from 'react'

import type { EnumValues } from '@/utils/types'

enum INPUT_TYPE {
  MIN, // 最小值
  MAX, // 最大值
}

type InputType = EnumValues<typeof INPUT_TYPE>

type ValuePair = (string | number | undefined)[];

type FormDigitRangeProps = {
  value?: ValuePair; // 表单控件的值
  onChange?: (value: ValuePair) => void; // 表单控件改变值的回调
  separator: string; // 分割线
  separatorGap: number; // 分割线和数据框的 gap
  placeholder: [string, string]; // 占位符
  suffix: string; // 后缀,不传则不显示
} & InputNumberProps

const FormDigitRange: FC<FormDigitRangeProps> = ({
  value = [],
  onChange,
  separator = '~',
  separatorGap = 15,
  placeholder = ['最小值', '最大值'],
  precision = 2,
  min = 0,
  max = 99999999.99,
  suffix,
  ...inputNumberProps
}) => {
  // 输入值失去焦点回调
  const handleChangeValue = (e: FocusEventHandler<HTMLInputElement>, type: InputType) => {
    // 获取输入框的值,这里转成 number 类型
    const result = e.target.value !== '' ? toNumber(e.target.value) : undefined;
    // 解构获取最值
    const [min, max] = value;
    switch (type) {
      case INPUT_TYPE.MIN:
        // 判断最小值是否大于最大值,为真就调换位置
        onChange?.(gt(result, max) ? [max, result] : [result, max])
        break;
      case INPUT_TYPE.MAX:
        // 判断最大值是否小于最小值,为真就调换位置
        onChange?.(gt(min, result) ? [result, min] : [min, result])
        break;
    }
  }
  // 渲染输入框
  const renderInputNumber = (type: InputType) => (
    <InputNumber
      {...inputNumberProps}
      min={min}
      max={max}
      value={toNumber(value[type])}
      precision={precision}
      placeholder={placeholder[type]}
      onBlur={(e) => handleChangeValue(e, type)}
      style={
  { width: '100%' }}
    />
  )

  return (
    <Row gutter={separatorGap} align='middle' wrap={false}>
      <Col flex={1}>
        {renderInputNumber(INPUT_TYPE.MIN)}
      </Col>
      <Col flex="none">
        <div>{separator}</div>
      </Col>
      <Col flex={1}>
        {renderInputNumber(INPUT_TYPE.MAX)}
      </Col>
      {
        suffix && (
          <Col flex="none">{suffix}</Col>
        )
      }
    </Row>
  )
}
export default FormDigitRange

代码不到100行,怎么样,是不是很容易?

使用方式

import { Button, Col, Form, Row, Space } from 'antd'
import { compact, isNumber } from 'lodash'
import React, { FC, useEffect, useState } from 'react'

import PageContainer from '@/components/PageContainer'

import FormDigitRange from './components/FormDigitRange'


const DataAcquisition: FC = () => {
  const [form] = Form.useForm();
  const [fields, setFields] = useState({});
  const onFinish = (values: any) => {
    setFields(values)
  };

  useEffect(() => {
    form.setFieldValue('money', undefined)
  }, [])
  return (
    <PageContainer title="数字范围输入组件">
      <Form form={form} onFinish={onFinish}>
        <Row>
          <Col span={12}>
            <Form.Item
              name="money"
              label="租金涨跌金额"
              rules={[
                { type: 'array', required: true, message: '' },
                () => ({
                  validator(_, value) {
                    if (!value || !compact(value).length) {
                      return Promise.reject(new Error('请输入租金涨跌金额'));
                    } else if (!isNumber(value[0])) {
                      return Promise.reject(new Error('请输入最小值'));
                    } else if (!isNumber(value[1])) {
                      return Promise.reject(new Error('请输入最大值'));
                    }
                    return Promise.resolve();
                  },
                }),
              ]}
            >
              <FormDigitRange suffix="元/㎡/月" />
            </Form.Item>
          </Col>
        </Row>
        <Row>
          <Col span={12}>
            <Space direction="vertical" size="middle" style={
  { display: 'flex' }} align='center'>
              <pre style={
  { background: '#f5f5f5', padding: '12px 20px', width: 400 }}>
                {JSON.stringify(fields, null, 2)}
              </pre>
              <Button htmlType="submit" type="primary">提交</Button>
            </Space>
          </Col>
        </Row>
      </Form>
    </PageContainer>
  )
}
export default DataAcquisition

参数说明

参数 说明 类型 默认值 是否必传
separator 分隔符 string ~ -
separatorGap 分隔符间距 number 15 -
placeholder 占位符 [string,string] ['最小值', '最大值'] -
precision 数值精度 number 2 -
min 最小值 number 0 -
max 最大值 number 99999999.99 -
suffix 后缀 string - -

除此之外支持所有 InputNumber属性

效果预览

image.png

注意事项

  1. 组件是根据公司具体业务需求开发的,不一定符合每个人的要求

  2. 该组件只是提供一个思路,可在此拓展更复杂的业务场景

相关文章
|
前端开发 JavaScript 测试技术
从零开始搭建react+typescript+antd+redux+less+vw自适应项目
从零开始搭建react+typescript+antd+redux+less+vw自适应项目
369 0
|
前端开发 JavaScript 数据安全/隐私保护
详解React antd中setFieldsValu的简便使用
详解React antd中setFieldsValu的简便使用
548 0
|
2月前
|
编解码 前端开发 JavaScript
js react antd 实现页面低分变率和高分变率下字体大小自适用,主要是配置antd
在React中结合Ant Design与媒体查询,通过less变量和响应式断点动态调整`@font-size-base`,实现多分辨率下字体自适应,提升跨设备体验。
80 2
|
3月前
|
前端开发 安全 数据安全/隐私保护
React - 实现一个基于 Antd 的密码强度校验组件
这篇文章介绍了一个基于 Nest 和 Umi 技术栈的个人项目开发中用到的密码强度校验组件的开发过程。作者首先在网上找不到满意的资料,于是决定自己开发该组件。文章依次介绍了效果预览、组件思想和组件开发的过程,并提供了相应的代码示例。最后,作者展示了实际效果,并提供了仓库地址供参考。
React - 实现一个基于 Antd 的密码强度校验组件
|
前端开发 JavaScript 网络架构
react对antd中Select组件二次封装
本文介绍了如何在React中对Ant Design(antd)的Select组件进行二次封装,包括创建MSelect组件、定义默认属性、渲染Select组件,并展示了如何使用Less进行样式定义和如何在项目中使用封装后的Select组件。
470 2
react对antd中Select组件二次封装
|
前端开发
React给antd中TreeSelect组件左侧加自定义图标icon
本文介绍了如何在React中为Ant Design的TreeSelect组件的每个树节点添加自定义图标,并解决了因缺少key属性而导致的警告问题,展示了如何通过递归函数处理treeData数据并为每个节点添加图标。
688 2
React给antd中TreeSelect组件左侧加自定义图标icon
|
前端开发
react使用antd中的Checkbox实现多选
在React项目中,通过Ant Design的Checkbox组件实现多选。引入Checkbox,使用Checkbox.Group来管理Checkbox,设置`value`属性绑定选中项数组,通过`onChange`更新数组。维护一个全选状态,根据选中项数量与总数决定全选按钮状态。全选按钮的`onChange`事件用于控制所有Checkbox的选中状态。
650 1
react使用antd中的Checkbox实现多选
|
前端开发
React添加路径别名alias、接受props默认值、并二次封装antd中Modal组件与使用
本文介绍了在React项目中如何添加路径别名alias以简化模块引入路径,设置组件props的默认值,以及如何二次封装Ant Design的Modal组件。文章还提供了具体的代码示例,包括配置Webpack的alias、设置defaultProps以及封装Modal组件的步骤和方法。
275 1
React添加路径别名alias、接受props默认值、并二次封装antd中Modal组件与使用
|
前端开发 JavaScript 区块链
react18函数组件+antd使用指南-使用代码集合以及报错记录汇总
本文介绍了多个React开发中常见的问题及其解决方案,包括但不限于:1)`useForm`实例未连接到任何`Form`元素的警告及解决方法;2)监听页面滚动事件的实现方式;3)React 18与antd 5.8.6中定制主题的方法;4)React结合antd 4.x版本自定义主题色的步骤;5)解决`ResizeObserver loop`相关报错的技巧;6)处理React设计表单时遇到的CDN资源加载失败问题;7)解决onClick事件传参问题;8)修复类型错误等。每部分均提供详细分析与实用代码示例,帮助开发者快速定位并解决问题。
320 3
|
前端开发 计算机视觉
React使用antd实现可编辑单元格
React结合Ant Design实现可编辑单元格的表格组件,通过EditableRow和EditableCell封装实现单元格编辑功能,并提供saveFun回调保存编辑内容。
557 1