Ant Design学习——DatePicker

2021SC@SDUSC

日期选择框DatePicker

用法:
一个输入或选择日期的控件。
当用户需要输入一个日期,可以点击标准输入框,弹出日期面板进行选择。

API

日期类组件包括以下五种形式。

  • DatePicker
  • DatePicker[picker=“month”]
  • DatePicker[picker=“week”]
  • DatePicker[picker=“year”]
  • DatePicker[picker=“quarter”] (4.1.0 新增)
  • RangePicker

国际化配置

import 'moment/locale/zh-cn';
import locale from 'antd/es/date-picker/locale/zh_CN';

<DatePicker locale={locale} />;
// 默认语言为 en-US,如果你需要设置其他语言,推荐在入口文件全局设置 locale
import moment from 'moment';
import 'moment/locale/zh-cn';
import locale from 'antd/lib/locale/zh_CN';

<ConfigProvider locale={locale}>
  <DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
</ConfigProvider>;

共同的API

DatePickerRangePicker 共享的 API。

参数说明类型默认值
allowClear是否显示清除按钮booleantrue
autoFocus自动获取焦点booleanfalse
bordered是否有边框booleantrue
className选择器 classNamestring-
dateRender自定义日期单元格的内容function(currentDate: moment, today: moment) => React.ReactNode-
disabled禁用booleanfalse
disabledDate不可选择的日期(currentDate: moment) => boolean-
dropdownClassName额外的弹出日历 classNamestring-
getPopupContainer定义浮层的容器,默认为 body 上新建 divfunction(trigger)-
inputReadOnly设置输入框为只读(避免在移动设备上打开虚拟键盘)booleanfalse
locale国际化配置object
nextIcon自定义下一个图标ReactNode-
open控制弹层是否展开boolean-
panelRender自定义渲染面板(panelNode) => ReactNode-
picker设置选择器类型date | week | month | quarter | yeardate
placeholder输入框提示文字string | [string, string]-
popupStyle额外的弹出日历样式CSSProperties{}
prevIcon自定义上一个图标ReactNode-
size输入框大小,large 高度为 40px,small 为 24px,默认是 32pxlarge | middle | small-
style自定义输入框样式CSSProperties{}
suffixIcon自定义的选择框后缀图标ReactNode-
superNextIcon自定义 << 切换图标ReactNode-
superPrevIcon自定义 >> 切换图标ReactNode-
onOpenChange弹出日历和关闭日历的回调function(open)-
onPanelChange日历面板切换的回调function(value, mode)-

DatePicker

参数说明类型默认值
defaultPickerValue默认面板日期moment-
defaultValue默认日期,如果开始时间或结束时间为 null 或者 undefined,日期范围将是一个开区间moment-
disabledTime不可选择的时间function(date)-
format设置日期格式,为数组时支持多格式匹配,展示以第一个为准。配置参考 moment.js,支持自定义格式string | (value: moment) => string | (string | (value: moment) => string)[]YYYY-MM-DD
renderExtraFooter在面板中添加额外的页脚(mode) => React.ReactNode-
showNow当设定了 showTime 的时候,面板是否显示“此刻”按钮boolean-
showTime增加时间选择功能Object | booleanTimePicker Options
showTime.defaultValue设置用户选择日期时默认的时分秒,例子momentmoment()
showToday是否展示“今天”按钮booleantrue
value日期moment-
onChange时间发生变化的回调function(date: moment, dateString: string)-
onOk点击确定按钮的回调function()-
onPanelChange日期面板变化时的回调function(value, mode)-

DatePicker[picker=year]

参数说明类型默认值
defaultPickerValue默认面板日期moment-
defaultValue默认日期moment-
format展示的日期格式,配置参考 moment.jsstringYYYY
renderExtraFooter在面板中添加额外的页脚() => React.ReactNode-
value日期moment-
onChange时间发生变化的回调,发生在用户选择时间时function(date: moment, dateString: string)-

DatePicker[picker=quarter]

4.1.0 新增。

参数说明类型默认值
defaultPickerValue默认面板日期moment-
defaultValue默认日期moment-
format展示的日期格式,配置参考 moment.jsstringYYYY-\QQ
renderExtraFooter在面板中添加额外的页脚() => React.ReactNode-
value日期moment-
onChange时间发生变化的回调,发生在用户选择时间时function(date: moment, dateString: string)-

DatePicker[picker=month]

参数说明类型默认值
defaultPickerValue默认面板日期moment-
defaultValue默认日期moment-
format展示的日期格式,配置参考 moment.jsstringYYYY-MM
monthCellRender自定义的月份内容渲染方法function(date, locale): ReactNode-
renderExtraFooter在面板中添加额外的页脚() => React.ReactNode-
value日期moment-
onChange时间发生变化的回调,发生在用户选择时间时function(date: moment, dateString: string)-

DatePicker[picker=week]

参数说明类型默认值
defaultPickerValue默认面板日期moment-
defaultValue默认日期moment-
format展示的日期格式,配置参考 moment.jsstringYYYY-wo
renderExtraFooter在面板中添加额外的页脚(mode) => React.ReactNode-
value日期moment-
onChange时间发生变化的回调,发生在用户选择时间时function(date: moment, dateString: string)-

RangePicker

参数说明类型默认值
allowEmpty允许起始项部分为空[boolean, boolean][false, false]
dateRender自定义日期单元格的内容。info 参数自 4.3.0 添加function(currentDate: moment, today: moment, info: { range: start | end }) => React.ReactNode-
defaultPickerValue默认面板日期moment[]-
defaultValue默认日期moment[]-
disabled禁用起始项[boolean, boolean]-
disabledTime不可选择的时间function(date: moment, partial: start | end)-
format展示的日期格式stringYYYY-MM-DD HH:mm:ss
ranges预设时间范围快捷选择{ [range: string]: moment[] } | { [range: string]: () => moment[] }-
renderExtraFooter在面板中添加额外的页脚() => React.ReactNode-
separator设置分隔符React.ReactNode<SwapRightOutlined />
showTime增加时间选择功能Object|booleanTimePicker Options
showTime.defaultValue设置用户选择日期时默认的时分秒moment[][moment(), moment()]
value日期moment[]-
onCalendarChange待选日期发生变化的回调。info 参数自 4.4.0 添加function(dates: [moment, moment], dateStrings: [string, string], info: { range:start|end })-
onChange日期范围发生变化的回调function(dates: [moment, moment], dateStrings: [string, string])-

部分源码

由于DataPicker有多种形式,因此代码偏多,但结构并不复杂
generateSinglePicker.tsx

import * as React from 'react';
import classNames from 'classnames';
import CalendarOutlined from '@ant-design/icons/CalendarOutlined';
import ClockCircleOutlined from '@ant-design/icons/ClockCircleOutlined';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import RCPicker from 'rc-picker';
import { PickerMode } from 'rc-picker/lib/interface';
import { GenerateConfig } from 'rc-picker/lib/generate/index';
import enUS from '../locale/en_US';
import { getPlaceholder } from '../util';
import devWarning from '../../_util/devWarning';
import { ConfigContext, ConfigConsumerProps } from '../../config-provider';
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
import SizeContext from '../../config-provider/SizeContext';
import {
  PickerProps,
  PickerLocale,
  PickerDateProps,
  PickerTimeProps,
  getTimeProps,
  Components,
} from '.';
import { PickerComponentClass } from './interface';

可以看到使用了react中的picker

export default function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
  type DatePickerProps = PickerProps<DateType>;

  function getPicker<InnerPickerProps extends DatePickerProps>(
    picker?: PickerMode,
    displayName?: string,
  ) {

主要的函数,generatePicker,内部是getPicker,用于选择DataPicker的类型

    class Picker extends React.Component<InnerPickerProps> {
      static contextType = ConfigContext;

      static displayName: string;

      context: ConfigConsumerProps;

      pickerRef = React.createRef<RCPicker<DateType>>();

      constructor(props: InnerPickerProps) {
        super(props);
        devWarning(
          picker !== 'quarter',
          displayName!,
          `DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,
        );
      }

      focus = () => {
        if (this.pickerRef.current) {
          this.pickerRef.current.focus();
        }
      };

      blur = () => {
        if (this.pickerRef.current) {
          this.pickerRef.current.blur();
        }
      };

      renderPicker = (contextLocale: PickerLocale) => {
        const locale = { ...contextLocale, ...this.props.locale };
        const { getPrefixCls, direction, getPopupContainer } = this.context;
        const {
          prefixCls: customizePrefixCls,
          getPopupContainer: customizeGetPopupContainer,
          className,
          size: customizeSize,
          bordered = true,
          placeholder,
          ...restProps
        } = this.props;
        const { format, showTime } = this.props as any;
        const prefixCls = getPrefixCls('picker', customizePrefixCls);

        const additionalProps = {
          showToday: true,
        };

        let additionalOverrideProps: any = {};
        if (picker) {
          additionalOverrideProps.picker = picker;
        }
        const mergedPicker = picker || this.props.picker;

        additionalOverrideProps = {
          ...additionalOverrideProps,
          ...(showTime ? getTimeProps({ format, picker: mergedPicker, ...showTime }) : {}),
          ...(mergedPicker === 'time'
            ? getTimeProps({ format, ...this.props, picker: mergedPicker })
            : {}),
        };
        const rootPrefixCls = getPrefixCls();

        return (
          <SizeContext.Consumer>
            {size => {
              const mergedSize = customizeSize || size;

              return (
                <RCPicker<DateType>
                  ref={this.pickerRef}
                  placeholder={getPlaceholder(mergedPicker, locale, placeholder)}
                  suffixIcon={
                    mergedPicker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />
                  }
                  clearIcon={<CloseCircleFilled />}
                  prevIcon={<span className={`${prefixCls}-prev-icon`} />}
                  nextIcon={<span className={`${prefixCls}-next-icon`} />}
                  superPrevIcon={<span className={`${prefixCls}-super-prev-icon`} />}
                  superNextIcon={<span className={`${prefixCls}-super-next-icon`} />}
                  allowClear
                  transitionName={`${rootPrefixCls}-slide-up`}
                  {...additionalProps}
                  {...restProps}
                  {...additionalOverrideProps}
                  locale={locale!.lang}
                  className={classNames(
                    {
                      [`${prefixCls}-${mergedSize}`]: mergedSize,
                      [`${prefixCls}-borderless`]: !bordered,
                    },
                    className,
                  )}
                  prefixCls={prefixCls}
                  getPopupContainer={customizeGetPopupContainer || getPopupContainer}
                  generateConfig={generateConfig}
                  components={Components}
                  direction={direction}
                />
              );
            }}
          </SizeContext.Consumer>
        );
      };

可以看出内部的Picker类继承了react组件InnerPickerProps
运用了react的Picker进行了实现,并附加了一些自己的属性

      render() {
        return (
          <LocaleReceiver componentName="DatePicker" defaultLocale={enUS}>
            {this.renderPicker}
          </LocaleReceiver>
        );
      }
    }

    if (displayName) {
      Picker.displayName = displayName;
    }

    return Picker as PickerComponentClass<InnerPickerProps>;
  }

渲染,并设置名称,最终getPicker函数返回Picker

  const DatePicker = getPicker<DatePickerProps>();
  const WeekPicker = getPicker<Omit<PickerDateProps<DateType>, 'picker'>>('week', 'WeekPicker');
  const MonthPicker = getPicker<Omit<PickerDateProps<DateType>, 'picker'>>('month', 'MonthPicker');
  const YearPicker = getPicker<Omit<PickerDateProps<DateType>, 'picker'>>('year', 'YearPicker');
  const TimePicker = getPicker<Omit<PickerTimeProps<DateType>, 'picker'>>('time', 'TimePicker');
  const QuarterPicker = getPicker<Omit<PickerTimeProps<DateType>, 'picker'>>(
    'quarter',
    'QuarterPicker',
  );

  return { DatePicker, WeekPicker, MonthPicker, YearPicker, TimePicker, QuarterPicker };

6种Picker运用getPicker生成,并返回

generateRangePicker.tsx
结构也较为类似

import * as React from 'react';
import classNames from 'classnames';
import CalendarOutlined from '@ant-design/icons/CalendarOutlined';
import ClockCircleOutlined from '@ant-design/icons/ClockCircleOutlined';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import SwapRightOutlined from '@ant-design/icons/SwapRightOutlined';
import { RangePicker as RCRangePicker } from 'rc-picker';
import { GenerateConfig } from 'rc-picker/lib/generate/index';
import enUS from '../locale/en_US';
import { ConfigContext, ConfigConsumerProps } from '../../config-provider';
import SizeContext from '../../config-provider/SizeContext';
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
import { getRangePlaceholder } from '../util';
import { RangePickerProps, PickerLocale, getTimeProps, Components } from '.';
import { PickerComponentClass } from './interface';

依旧使用react的picker

export default function generateRangePicker<DateType>(
  generateConfig: GenerateConfig<DateType>,
): PickerComponentClass<RangePickerProps<DateType>> {
  class RangePicker extends React.Component<RangePickerProps<DateType>> {

使用了与generateSinglePicker中相似的结构,区别只是不需要选择是哪种DatePicker,因为只有一种rangepicker。

generatePicker
index.tsx

export function getTimeProps<DateType>(
  props: { format?: string; picker?: PickerMode } & SharedTimeProps<DateType>,
) {
  const { format, picker, showHour, showMinute, showSecond, use12Hours } = props;

  const firstFormat = toArray(format)[0];
  const showTimeObj: SharedTimeProps<DateType> = { ...props };

  if (firstFormat && typeof firstFormat === 'string') {
    if (!firstFormat.includes('s') && showSecond === undefined) {
      showTimeObj.showSecond = false;
    }
    if (!firstFormat.includes('m') && showMinute === undefined) {
      showTimeObj.showMinute = false;
    }
    if (!firstFormat.includes('H') && !firstFormat.includes('h') && showHour === undefined) {
      showTimeObj.showHour = false;
    }

    if ((firstFormat.includes('a') || firstFormat.includes('A')) && use12Hours === undefined) {
      showTimeObj.use12Hours = true;
    }
  }

  if (picker === 'time') {
    return showTimeObj;
  }

  if (typeof firstFormat === 'function') {
    // format of showTime should use default when format is custom format function
    delete showTimeObj.format;
  }

  return {
    showTime: showTimeObj,
  };
}

对于时间格式的处理,返回时间的对象

type InjectDefaultProps<Props> = Omit<
  Props,
  | 'locale'
  | 'generateConfig'
  | 'hideHeader'
  | 'components'
> & {
  locale?: PickerLocale;
  size?: SizeType;
  bordered?: boolean;
};

Omit辅助类型用于从一个类型中剔除部分属性,然后返回一个新类型
此处即为剔除
‘locale’
‘generateConfig’
‘hideHeader’
‘components’
之后这个类型又加上了locale size bordered属性

function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
  // =========================== Picker ===========================
  const { DatePicker, WeekPicker, MonthPicker, YearPicker, TimePicker, QuarterPicker } =
    generateSinglePicker(generateConfig);

  // ======================== Range Picker ========================
  const RangePicker = generateRangePicker(generateConfig);

  // =========================== Export ===========================
  type MergedDatePickerType = typeof DatePicker & {
    WeekPicker: typeof WeekPicker;
    MonthPicker: typeof MonthPicker;
    YearPicker: typeof YearPicker;
    RangePicker: typeof RangePicker;
    TimePicker: typeof TimePicker;
    QuarterPicker: typeof QuarterPicker;
  };

  const MergedDatePicker = DatePicker as MergedDatePickerType;
  MergedDatePicker.WeekPicker = WeekPicker;
  MergedDatePicker.MonthPicker = MonthPicker;
  MergedDatePicker.YearPicker = YearPicker;
  MergedDatePicker.RangePicker = RangePicker;
  MergedDatePicker.TimePicker = TimePicker;
  MergedDatePicker.QuarterPicker = QuarterPicker;

  return MergedDatePicker;
}

export default generatePicker;

最终导出的是generatePicker方法,用于生成各种Picker

外层index.tsx

import { Moment } from 'moment';
import momentGenerateConfig from 'rc-picker/lib/generate/moment';
import generatePicker, {
  PickerProps,
  PickerDateProps,
  RangePickerProps as BaseRangePickerProps,
} from './generatePicker';

export type DatePickerProps = PickerProps<Moment>;
export type MonthPickerProps = Omit<PickerDateProps<Moment>, 'picker'>;
export type WeekPickerProps = Omit<PickerDateProps<Moment>, 'picker'>;
export type RangePickerProps = BaseRangePickerProps<Moment>;

const DatePicker = generatePicker<Moment>(momentGenerateConfig);

export default DatePicker;

DataPicker由generatePicker方法生成。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值