概述
Ant-design 源码分析之数据展示(三)Calendar
2021SC@SDUSC
一、组件结构
1、ant代码结构
2、rc-ant代码结构
3、组件结构
二、antd组件调用关系
1、generateCalendar.tsx
导入相应模块以及相应的ICON图标
import * as React from 'react';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import classNames from 'classnames';
import padStart from 'lodash/padStart';
import { PickerPanel as RCPickerPanel } from 'rc-picker';
import { Locale } from 'rc-picker/lib/interface';
import { GenerateConfig } from 'rc-picker/lib/generate';
import {
PickerPanelBaseProps as RCPickerPanelBaseProps,
PickerPanelDateProps as RCPickerPanelDateProps,
PickerPanelTimeProps as RCPickerPanelTimeProps,
} from 'rc-picker/lib/PickerPanel';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import enUS from './locale/en_US';
import { ConfigContext } from '../config-provider';
import CalendarHeader from './Header';
创建了CalendarProps接口。
export interface CalendarProps<DateType> {
prefixCls?: string;
className?: string;
style?: React.CSSProperties;
locale?: typeof enUS;
validRange?: [DateType, DateType];
disabledDate?: (date: DateType) => boolean;
dateFullCellRender?: (date: DateType) => React.ReactNode;
dateCellRender?: (date: DateType) => React.ReactNode;
monthFullCellRender?: (date: DateType) => React.ReactNode;
monthCellRender?: (date: DateType) => React.ReactNode;
headerRender?: HeaderRender<DateType>;
value?: DateType;
defaultValue?: DateType;
mode?: CalendarMode;
fullscreen?: boolean;
onChange?: (date: DateType) => void;
onPanelChange?: (date: DateType, mode: CalendarMode) => void;
onSelect?: (date: DateType) => void;
}
dateCellRender:自定义渲染日期单元格,返回内容会被追加到单元格,类型为function(date: moment): ReactNode。
dateFullCellRender:自定义渲染日期单元格,返回内容覆盖单元格,类型为function(date: moment): ReactNode。
defaultValue:默认展示的日期类型为moment。
disabledDate:不可选择的日期,参数为当前 value,注意使用时不要直接修改,类型为(currentDate: moment) => boolean。
fullscreen:是否全屏显示,类型为boolean。
headerRender:自定义头部内容,类型为function(object:{value: moment, type: string, onChange: f(), onTypeChange: f()})。
locale:国际化配置,类型为object。
mode:初始模式,类型为month | year。
monthCellRender:自定义渲染月单元格,返回内容会被追加到单元格,类型为function(date: moment): ReactNode。
monthFullCellRender:自定义渲染月单元格,返回内容覆盖单元格,类型为function(date: moment): ReactNode。
validRange:设置可以显示的日期,类型为[moment, moment] 。
value 展示日期 moment -
onChange:日期变化回调,类型为function(date: moment)。
onPanelChange:日期面板变化回调,类型为function(date: moment, mode: string)。
onSelect:点击选择日期回调,类型为function(date: moment)。
通过接口实现了Calendar。
const Calendar = (props: CalendarProps<DateType>) => {
const {
prefixCls: customizePrefixCls,
className,
style,
dateFullCellRender,
dateCellRender,
monthFullCellRender,
monthCellRender,
headerRender,
value,
defaultValue,
disabledDate,
mode,
validRange,
fullscreen = true,
onChange,
onPanelChange,
onSelect,
} = props;
设置样式前缀 prefixCls:
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('picker', customizePrefixCls);
const calendarPrefixCls = `${prefixCls}-calendar`;
返回日期
const today = generateConfig.getNow();
状态
// 设置Value
const [mergedValue, setMergedValue] = useMergedState(() => value || generateConfig.getNow(), {
defaultValue,
value,
});
// 设置Mode
const [mergedMode, setMergedMode] = useMergedState('month', {
value: mode,
});
const panelMode = React.useMemo<'month' | 'date'>(
() => (mergedMode === 'year' ? 'month' : 'date'),
[mergedMode],
);
// 设置Disabled Date
const mergedDisabledDate = React.useCallback(
(date: DateType) => {
const notInRange = validRange
? generateConfig.isAfter(validRange[0], date) ||
generateConfig.isAfter(date, validRange[1])
: false;
return notInRange || !!disabledDate?.(date);
},
[disabledDate, validRange],
);
//界面触发器
const triggerPanelChange = (date: DateType, newMode: CalendarMode) => {
onPanelChange?.(date, newMode);
};
const triggerChange = (date: DateType) => {
setMergedValue(date);
if (!isSameDate(date, mergedValue)) {
// Trigger when month panel switch month
if (
(panelMode === 'date' && !isSameMonth(date, mergedValue)) ||
(panelMode === 'month' && !isSameYear(date, mergedValue))
) {
triggerPanelChange(date, mergedMode);
}
onChange?.(date);
}
};
const triggerModeChange = (newMode: CalendarMode) => {
setMergedMode(newMode);
triggerPanelChange(mergedValue, newMode);
};
const onInternalSelect = (date: DateType) => {
triggerChange(date);
onSelect?.(date);
};
//获取时间
const getDefaultLocale = () => {
const { locale } = props;
const result = {
...enUS,
...locale,
};
result.lang = {
...result.lang,
...((locale || {}) as any).lang,
};
return result;
};
//显示日期
const dateRender = React.useCallback(
(date: DateType): React.ReactNode => {
if (dateFullCellRender) {
return dateFullCellRender(date);
}
return (
<div
className={classNames(`${prefixCls}-cell-inner`, `${calendarPrefixCls}-date`, {
[`${calendarPrefixCls}-date-today`]: isSameDate(today, date),
})}
>
<div className={`${calendarPrefixCls}-date-value`}>
{padStart(String(generateConfig.getDate(date)), 2, '0')}
</div>
<div className={`${calendarPrefixCls}-date-content`}>
{dateCellRender && dateCellRender(date)}
</div>
</div>
);
},
[dateFullCellRender, dateCellRender],
);
//显示月份
const monthRender = React.useCallback(
(date: DateType, locale: Locale): React.ReactNode => {
if (monthFullCellRender) {
return monthFullCellRender(date);
}
const months = locale.shortMonths || generateConfig.locale.getShortMonths!(locale.locale);
return (
<div
className={classNames(`${prefixCls}-cell-inner`, `${calendarPrefixCls}-date`, {
[`${calendarPrefixCls}-date-today`]: isSameMonth(today, date),
})}
>
<div className={`${calendarPrefixCls}-date-value`}>
{months[generateConfig.getMonth(date)]}
</div>
<div className={`${calendarPrefixCls}-date-content`}>
{monthCellRender && monthCellRender(date)}
</div>
</div>
);
},
[monthFullCellRender, monthCellRender],
);
return (
<LocaleReceiver componentName="Calendar" defaultLocale={getDefaultLocale}>
{(mergedLocale: any) => (
<div
className={classNames(
calendarPrefixCls,
{
[`${calendarPrefixCls}-full`]: fullscreen,
[`${calendarPrefixCls}-mini`]: !fullscreen,
[`${calendarPrefixCls}-rtl`]: direction === 'rtl',
},
className,
)}
style={style}
>
{headerRender ? (
headerRender({
value: mergedValue,
type: mergedMode,
onChange: onInternalSelect,
onTypeChange: triggerModeChange,
})
) : (
<CalendarHeader
prefixCls={calendarPrefixCls}
value={mergedValue}
generateConfig={generateConfig}
mode={mergedMode}
fullscreen={fullscreen}
locale={mergedLocale.lang}
validRange={validRange}
onChange={onInternalSelect}
onModeChange={triggerModeChange}
/>
)}
<RCPickerPanel
value={mergedValue}
prefixCls={prefixCls}
locale={mergedLocale.lang}
generateConfig={generateConfig}
dateRender={dateRender}
monthCellRender={date => monthRender(date, mergedLocale.lang)}
onSelect={onInternalSelect}
mode={panelMode}
picker={panelMode as any}
disabledDate={mergedDisabledDate}
hideHeader
/>
</div>
)}
</LocaleReceiver>
);
};
三、rc-antd组件调用关系
导入相应模块
1、Rc-picker
PickerPanel.tsx
导入相应模块
import * as React from 'react';
import classNames from 'classnames';
import KeyCode from 'rc-util/lib/KeyCode';
import warning from 'rc-util/lib/warning';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import type { SharedTimeProps } from './panels/TimePanel';
import TimePanel from './panels/TimePanel';
import DatetimePanel from './panels/DatetimePanel';
import DatePanel from './panels/DatePanel';
import WeekPanel from './panels/WeekPanel';
import MonthPanel from './panels/MonthPanel';
import QuarterPanel from './panels/QuarterPanel';
import YearPanel from './panels/YearPanel';
import DecadePanel from './panels/DecadePanel';
import type { GenerateConfig } from './generate';
import type {
Locale,
PanelMode,
PanelRefProps,
PickerMode,
DisabledTime,
OnPanelChange,
Components,
} from './interface';
import { isEqual } from './utils/dateUtil';
import PanelContext from './PanelContext';
import type { DateRender } from './panels/DatePanel/DateBody';
import { PickerModeMap } from './utils/uiUtil';
import type { MonthCellRender } from './panels/MonthPanel/MonthBody';
import RangeContext from './RangeContext';
import getExtraFooter from './utils/getExtraFooter';
import getRanges from './utils/getRanges';
import { getLowerBoundTime, setDateTime, setTime } from './utils/timeUtil';
对象
function PickerPanel<DateType>(props: PickerPanelProps<DateType>) {
const {
prefixCls = 'rc-picker',
className,
style,
locale,
generateConfig,
value,
defaultValue,
pickerValue,
defaultPickerValue,
disabledDate,
mode,
picker = 'date',
tabIndex = 0,
showNow,
showTime,
showToday,
renderExtraFooter,
hideHeader,
onSelect,
onChange,
onPanelChange,
onMouseDown,
onPickerValueChange,
onOk,
components,
direction,
hourStep = 1,
minuteStep = 1,
secondStep = 1,
} = props as MergedPickerPanelProps<DateType>;
//是否需要确认
const needConfirmButton: boolean = (picker === 'date' && !!showTime) || picker === 'time';
//判断是否为0
const isHourStepValid = 24 % hourStep === 0;
const isMinuteStepValid = 60 % minuteStep === 0;
const isSecondStepValid = 60 % secondStep === 0;
if (process.env.NODE_ENV !== 'production') {
warning(!value || generateConfig.isValidate(value), 'Invalidate date pass to `value`.');
warning(!value || generateConfig.isValidate(value), 'Invalidate date pass to `defaultValue`.');
warning(isHourStepValid, ``hourStep` ${hourStep} is invalid. It should be a factor of 24.`);
warning(
isMinuteStepValid,
``minuteStep` ${minuteStep} is invalid. It should be a factor of 60.`,
);
warning(
isSecondStepValid,
``secondStep` ${secondStep} is invalid. It should be a factor of 60.`,
);
}
最后
以上就是闪闪缘分为你收集整理的Ant-design 源码分析之数据展示(三)Calendar的全部内容,希望文章能够帮你解决Ant-design 源码分析之数据展示(三)Calendar所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复