React组件 -- 双DatePicker

按照业务需求,需要封装一个组件。这个组件的功能为,显示为两个DatePicker,第一个是起始时间,第二个是终止时间;起始时间和终止时间可以不填,他们都有默认值;但是如果两个时间都存在的时候就必须保证结束时间不小于开始时间。

在这个组件封装的过程中,比较重要的几点在于:

    1. 使用antd组件并对其封装
    1. 使用styled-components强行改变antd组件内部样式
    1. 使用moment库对选择的日期进行序列化和反序列化
    1. 使用国际化字段及相关的方法getIntl
    1. 使用antd提供的Row Col来排布页面中的元素
    1. 使用Form.Item中的rules属性来保证结束日期大于开始日期
    1. 使用IDatePicker组件的disableData来自定义选择日期为今天以前

封装组件内容:

jsx 复制代码
import React from 'react';
import { Row, Col, Form, DatePicker } from 'antd';
import styled from 'styled-components';
import { getIntl } from '../../utils';

const ILabel = styled.label`
  &::after {
    content: ':';
    position: relative;
    top: -0.5px;
    margin: 0 8px 0 2px;
  }
`;

const IDatePicker = styled(DatePicker)`
  &.ant-picker {
    width: 100% !important;
  }
`;

const CustomDatePicker = ({
  formRef,
  disabledDate,
  span = 5,
  itemName = 'displayPeriod',
  startDateName = 'listingDate',
  endDateName = 'deListingDate',
  dateSpan = 10,
  arrowSpan = 3,
  arrowPosition = 'start',
}) => {
  return (
    <Row>
      <Col span={span} style={{ padding: 0, textAlign: 'end' }}>
        <ILabel for={itemName} title={itemName}>{`${getIntl(
          'NF.Content',
        )}`}</ILabel>
      </Col>
      <Col span={24 - span} style={{ padding: 0 }}>
        <Row className="ant-form-item">
          <Col span={dateSpan}>
            <Row>
              <Form.Item
                className="custom-date-picker"
                name={startDateName}
                style={{ marginBottom: 6, width: '100%' }}
                help="It will be visible after the start date. Visible immediately when empty."
              >
                <IDatePicker
                  placeholder="Select start date"
                  // value={timeRange}
                  format="MM/DD, YYYY"
                  // onChange={onlistingDateChange}
                  disabledDate={disabledDate}
                />
              </Form.Item>
            </Row>
          </Col>
          <Col span={arrowSpan}>
            <Row
              style={{
                height: 31.6,
                display: 'flex',
                alignItems: 'center',
                justifyContent: arrowPosition,
              }}
            >
              <svg
                width="12"
                height="6"
                viewBox="0 0 12 6"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  d="M11.6402 4.31563L9.07767 1.06563C9.03094 1.00629 8.97138 0.958321 8.90346 0.925306C8.83553 0.892291 8.76101 0.875092 8.68549 0.875H7.67299C7.5683 0.875 7.51049 0.995312 7.57455 1.07812L9.82924 3.9375H0.372986C0.304236 3.9375 0.247986 3.99375 0.247986 4.0625V5C0.247986 5.06875 0.304236 5.125 0.372986 5.125H11.2464C11.6652 5.125 11.898 4.64375 11.6402 4.31563Z"
                  fill="black"
                  fill-opacity="0.25"
                />
              </svg>
            </Row>
          </Col>
          <Col span={dateSpan}>
            <Row>
              <Form.Item
                className="custom-date-picker"
                name={endDateName}
                style={{ marginBottom: 6, width: '100%' }}
                // onChange={onDelistingDateChange}
                help="It will be invisible after the end date. Always visible when empty."
                rules={[
                  {
                    validator: () => {
                      const values = formRef.current?.getFieldsValue();
                      const listingDate = values[startDateName];
                      const deListingDate = values[endDateName];
                      if (deListingDate && listingDate) {
                        const compare = deListingDate.diff(listingDate);

                        if (compare > 0) {
                          return Promise.resolve();
                        }
                        return Promise.reject('Please upload');
                      }
                      return Promise.resolve();
                    },
                    message: `The end date must be later than the start date`,
                  },
                ]}
              >
                <IDatePicker
                  placeholder="Select end date"
                  // value={timeRange}
                  format="MM/DD, YYYY"
                  // onChange={onDelistingDateChange}
                  disabledDate={disabledDate}
                />
              </Form.Item>
            </Row>
          </Col>
        </Row>
      </Col>
    </Row>
  );
};

export default CustomDatePicker;

自定义日期规则:

jsx 复制代码
// 自定义disabledDate函数
function disabledDate(current) {
  const today = moment();
  const nextYear = moment().add(365, 'days');
  return current && (current < today || current > nextYear);
}
相关推荐
键盘不能没有CV键1 天前
【图片处理】✈️HTML转图片字体异常处理
前端·javascript·html
yantuguiguziPGJ1 天前
WPF 联合 Web 开发调试流程梳理(基于 Microsoft.Web.WebView2)
前端·microsoft·wpf
大飞记Python1 天前
部门管理|“编辑部门”功能实现(Django5零基础Web平台)
前端·数据库·python·django
tsumikistep1 天前
【前端】前端运行环境的结构
前端
你的人类朋友1 天前
【Node】认识multer库
前端·javascript·后端
Aitter1 天前
PDF和Word文件转换为Markdown的技术实现
前端·ai编程
mapbar_front1 天前
面试问题—上家公司的离职原因
前端·面试
昔人'1 天前
css使用 :where() 来简化大型 CSS 选择器列表
前端·css
昔人'1 天前
css `dorp-shadow`
前端·css
流***陌1 天前
扭蛋机 Roll 福利房小程序前端功能设计:融合趣味互动与福利适配
前端·小程序