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);
}
相关推荐
RPGMZ11 分钟前
RPGMZ游戏引擎 一个窗口 文本居中显示
开发语言·javascript·游戏引擎·rpgmz
海石5 小时前
📱随时随地大小编:TraeSolo 移动端初体验
前端·ai编程·trae
爱滑雪的码农7 小时前
详细说说React大型项目结构以及日常开发核心语法
前端·javascript·react.js
七牛开发者7 小时前
HTML is the new Markdown:来自 Claude Code 团队的实践
前端·人工智能·语言模型·html
@大迁世界8 小时前
43.HTML 事件处理和 React 事件处理有什么区别?
前端·javascript·react.js·html·ecmascript
CloneCello8 小时前
AI时代程序员认知调整指南
前端
ZC跨境爬虫8 小时前
跟着 MDN 学 HTML day_38:(DocumentFragment 文档片段接口详解)
前端·javascript·ui·html·音视频
@大迁世界9 小时前
41.ShadCN 是什么?它如何和 Tailwind CSS 集成,从而更容易构建可访问且可自定义的 React 组件?
前端·javascript·css·react.js·前端框架
千叶风行10 小时前
Text-to-SQL 技术设计与注意事项
前端·人工智能·后端
软件开发技术深度爱好者10 小时前
HTML5+JavaScript读取DOCX 文档完整内容
前端·html5