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);
}
相关推荐
布列瑟农的星空15 分钟前
大话设计模式——关注点分离原则下的事件处理
前端·后端·架构
山有木兮木有枝_17 分钟前
node文章生成器
javascript·node.js
yvvvy33 分钟前
前端必懂的 Cache 缓存机制详解
前端
北海几经夏1 小时前
React自定义Hook
前端·react.js
龙在天1 小时前
从代码到屏幕,浏览器渲染网页做了什么❓
前端
TimelessHaze1 小时前
【performance面试考点】让面试官眼前一亮的performance性能优化
前端·性能优化·trae
yes or ok1 小时前
前端工程师面试题-vue
前端·javascript·vue.js
我要成为前端高手1 小时前
给不支持摇树的三方库(phaser) tree-shake?
前端·javascript
Noxi_lumors2 小时前
VITE BALABALA require balabla not supported
前端·vite
周胜22 小时前
node-sass
前端