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
DatePicker
、 RangePicker
共享的 API。
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
allowClear | 是否显示清除按钮 | boolean | true |
autoFocus | 自动获取焦点 | boolean | false |
bordered | 是否有边框 | boolean | true |
className | 选择器 className | string | - |
dateRender | 自定义日期单元格的内容 | function(currentDate: moment, today: moment) => React.ReactNode | - |
disabled | 禁用 | boolean | false |
disabledDate | 不可选择的日期 | (currentDate: moment) => boolean | - |
dropdownClassName | 额外的弹出日历 className | string | - |
getPopupContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | - |
inputReadOnly | 设置输入框为只读(避免在移动设备上打开虚拟键盘) | boolean | false |
locale | 国际化配置 | object | ) |
nextIcon | 自定义下一个图标 | ReactNode | - |
open | 控制弹层是否展开 | boolean | - |
panelRender | 自定义渲染面板 | (panelNode) => ReactNode | - |
picker | 设置选择器类型 | date | week | month | quarter | year | date |
placeholder | 输入框提示文字 | string | [string, string] | - |
popupStyle | 额外的弹出日历样式 | CSSProperties | {} |
prevIcon | 自定义上一个图标 | ReactNode | - |
size | 输入框大小,large 高度为 40px,small 为 24px,默认是 32px | large | 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 | boolean | TimePicker Options |
showTime.defaultValue | 设置用户选择日期时默认的时分秒,例子 | moment | moment() |
showToday | 是否展示“今天”按钮 | boolean | true |
value | 日期 | moment | - |
onChange | 时间发生变化的回调 | function(date: moment, dateString: string) | - |
onOk | 点击确定按钮的回调 | function() | - |
onPanelChange | 日期面板变化时的回调 | function(value, mode) | - |
DatePicker[picker=year]
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
defaultPickerValue | 默认面板日期 | moment | - |
defaultValue | 默认日期 | moment | - |
format | 展示的日期格式,配置参考 moment.js | string | YYYY |
renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - |
value | 日期 | moment | - |
onChange | 时间发生变化的回调,发生在用户选择时间时 | function(date: moment, dateString: string) | - |
DatePicker[picker=quarter]
4.1.0
新增。
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
defaultPickerValue | 默认面板日期 | moment | - |
defaultValue | 默认日期 | moment | - |
format | 展示的日期格式,配置参考 moment.js | string | YYYY-\QQ |
renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - |
value | 日期 | moment | - |
onChange | 时间发生变化的回调,发生在用户选择时间时 | function(date: moment, dateString: string) | - |
DatePicker[picker=month]
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
defaultPickerValue | 默认面板日期 | moment | - |
defaultValue | 默认日期 | moment | - |
format | 展示的日期格式,配置参考 moment.js | string | YYYY-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.js | string | YYYY-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 | 展示的日期格式 | string | YYYY-MM-DD HH:mm:ss |
ranges | 预设时间范围快捷选择 | { [range: string]: moment[] } | { [range: string]: () => moment[] } | - |
renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - |
separator | 设置分隔符 | React.ReactNode | <SwapRightOutlined /> |
showTime | 增加时间选择功能 | Object|boolean | TimePicker 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方法生成。