Ant Design时间组件详解:日期选择器与日历功能实现
组件概述
Ant Design提供了丰富的时间处理组件,主要包括日期选择框(DatePicker)和日历(Calendar)两大类。这些组件基于dayjs库开发,支持多种日期格式和交互方式,能够满足企业级应用的各种时间选择需求。
日期选择框组件位于components/date-picker目录下,提供了日期、时间、月份、年份等多种选择模式。日历组件位于components/calendar目录下,主要用于按日历形式展示数据。
日期选择器(DatePicker)详解
基本使用
日期选择器的基础用法非常简单,导入组件后直接使用即可:
import { DatePicker } from 'antd';
import dayjs from 'dayjs';
function App() {
return <DatePicker defaultValue={dayjs('2023-01-01')} />;
}
这个例子展示了最基本的日期选择器,用户可以点击输入框弹出日期面板进行选择。默认情况下,组件会显示当前日期,并允许用户选择任意日期。
核心功能
1. 多种选择模式
DatePicker提供了多种选择模式,可以通过picker属性进行配置:
// 日期选择
<DatePicker picker="date" />
// 月份选择
<DatePicker picker="month" />
// 年份选择
<DatePicker picker="year" />
// 季度选择 (4.1.0 新增)
<DatePicker picker="quarter" />
// 周选择
<DatePicker picker="week" />
这些不同的选择模式对应着不同的业务场景,例如选择生日可以使用日期模式,选择财政季度可以使用季度模式。
2. 范围选择
RangePicker允许用户选择一个日期范围,非常适合需要选择开始和结束日期的场景:
import { DatePicker } from 'antd';
const { RangePicker } = DatePicker;
function App() {
return <RangePicker />;
}
范围选择器默认会显示两个输入框,分别对应开始日期和结束日期。用户可以通过预设范围快速选择常用的日期范围,如最近7天、最近30天等。
3. 日期格式自定义
可以通过format属性自定义日期的显示格式,配置参考dayjs#format:
<DatePicker format="YYYY/MM/DD" />
<DatePicker format="YYYY年MM月DD日" />
<RangePicker format={['YYYY-MM-DD', 'YYYY-MM-DD']} />
4. 禁用日期和时间
通过disabledDate和disabledTime属性可以禁用特定的日期和时间:
// 禁用今天之前的日期
<DatePicker
disabledDate={(current) => current && current < dayjs().startOf('day')}
/>
// 禁用特定时间
<DatePicker
showTime
disabledTime={() => ({
disabledHours: () => [0, 1, 2, 3, 4, 5, 6, 7, 22, 23],
})}
/>
高级功能
1. 时间选择
通过设置showTime属性,可以在日期选择器中添加时间选择功能:
<DatePicker showTime />
这在需要精确到小时、分钟的场景中非常有用,如会议安排、航班预订等。
2. 预设范围
使用presets属性可以添加预设的日期范围,方便用户快速选择常用的日期范围:
<RangePicker
presets={[
{ label: '今天', value: [dayjs(), dayjs()] },
{ label: '昨天', value: [dayjs().subtract(1, 'day'), dayjs().subtract(1, 'day')] },
{ label: '近7天', value: [dayjs().subtract(6, 'day'), dayjs()] },
]}
/>
3. 自定义单元格
从5.4.0版本开始,可以使用cellRender属性自定义日期单元格的内容:
<DatePicker
cellRender={(current, info) => {
// 为每月1号添加特殊标记
if (current.date() === 1) {
return (
<div>
<span>{current.date()}</span>
<span style={{ color: 'red', fontSize: '12px' }}>月初</span>
</div>
);
}
return info.originNode;
}}
/>
这个功能可以用于突出显示特殊日期,如节假日、重要事件等。
API参考
日期选择器的完整API可以在components/date-picker/index.zh-CN.md中查看。主要属性包括:
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| defaultValue | 默认日期 | dayjs | - |
| value | 日期 | dayjs | - |
| format | 日期格式 | string | 'YYYY-MM-DD' |
| disabled | 是否禁用 | boolean | false |
| disabledDate | 不可选择的日期 | function(currentDate) | - |
| showTime | 是否显示时间选择 | boolean | false |
| picker | 选择器类型 | 'date' | 'week' | 'month' | 'quarter' | 'year' | 'date' |
| onChange | 日期变化回调 | function(date, dateString) | - |
日历(Calendar)详解
基本使用
日历组件的基本用法如下:
import { Calendar } from 'antd';
function onSelect(date) {
console.log('Selected date:', date);
}
function App() {
return <Calendar onSelect={onSelect} />;
}
默认情况下,日历会全屏显示,用户可以点击日期进行选择,也可以通过顶部的导航切换月份和年份。
核心功能
1. 自定义单元格
使用cellRender属性可以自定义日历单元格的内容:
<Calendar
cellRender={(current, today, info) => {
// 为今天添加特殊样式
if (current.isSame(today, 'day')) {
return (
<div style={{ backgroundColor: '#e6f7ff', borderRadius: '50%', width: '24px', height: '24px', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto' }}>
{current.date()}
</div>
);
}
return info.originNode;
}}
/>
2. 通知事项日历
日历组件非常适合展示日程安排等信息:
function App() {
const events = [
{ date: '2023-06-12', title: '团队会议' },
{ date: '2023-06-15', title: '项目截止' },
{ date: '2023-06-20', title: '产品发布' },
];
return (
<Calendar
cellRender={(current) => {
const event = events.find(e => current.isSame(e.date, 'day'));
if (event) {
return (
<div>
<span>{current.date()}</span>
<div style={{ fontSize: '12px', color: '#1890ff' }}>{event.title}</div>
</div>
);
}
return current.date();
}}
/>
);
}
3. 选择功能
通过onSelect回调函数可以获取用户选择的日期:
<Calendar
onSelect={(date, { source }) => {
if (source === 'date') {
console.log('用户选择了日期:', date.format('YYYY-MM-DD'));
}
}}
/>
source参数可以判断选择的来源,可能的值包括'year'、'month'、'date'和'customize'。
高级用法
1. 卡片模式
设置fullscreen属性为false可以将日历显示为卡片模式,适合嵌入到其他容器中:
<Calendar fullscreen={false} />
2. 自定义头部
使用headerRender属性可以自定义日历的头部内容:
<Calendar
headerRender={({ value, type, onChange, onTypeChange }) => {
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<button onClick={() => onChange(value.subtract(1, type))}>上月</button>
<h3 style={{ margin: '0 16px' }}>{value.format(type === 'month' ? 'YYYY年MM月' : 'YYYY年')}</h3>
<button onClick={() => onChange(value.add(1, type))}>下月</button>
<button onClick={() => onTypeChange(type === 'month' ? 'year' : 'month')} style={{ marginLeft: '16px' }}>
{type === 'month' ? '切换到年视图' : '切换到月视图'}
</button>
</div>
);
}}
/>
3. 农历支持
日历组件支持农历显示,只需引入相应的dayjs插件:
import dayjs from 'dayjs';
import农历 from 'dayjs/plugin/lunar';
dayjs.extend(农历);
<Calendar
cellRender={(current) => {
return (
<div style={{ textAlign: 'center' }}>
<div>{current.date()}</div>
<div style={{ fontSize: '12px', color: '#999' }}>{current.lunar().format('MM-DD')}</div>
</div>
);
}}
/>
API参考
日历组件的完整API可以在components/calendar/index.zh-CN.md中查看。主要属性包括:
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| defaultValue | 默认展示的日期 | dayjs | - |
| value | 展示日期 | dayjs | - |
| fullscreen | 是否全屏显示 | boolean | true |
| cellRender | 自定义单元格内容 | function(current, today, info) | - |
| onSelect | 选择日期回调 | function(date, info) | - |
| onPanelChange | 日期面板变化回调 | function(date, mode) | - |
| mode | 初始模式 | 'month' | 'year' | 'month' |
实际应用案例
1. 酒店预订日期选择
import { DatePicker, Card, Typography } from 'antd';
import { CalendarOutlined } from '@ant-design/icons';
import dayjs from 'dayjs';
const { RangePicker } = DatePicker;
const { Title, Text } = Typography;
function HotelBooking() {
const [range, setRange] = useState([
dayjs().add(1, 'day'),
dayjs().add(3, 'day'),
]);
const disabledDate = (current) => {
// 禁用今天及之前的日期
return current && current < dayjs().endOf('day');
};
return (
<Card title="酒店预订" bordered={false}>
<Title level={5}>选择入住和退房日期</Title>
<RangePicker
disabledDate={disabledDate}
defaultValue={range}
onChange={setRange}
format="YYYY-MM-DD"
renderExtraFooter={() => (
<div style={{ textAlign: 'center', padding: '16px' }}>
<Text type="secondary">
{range && range[0] && range[1]
? `共 ${range[1].diff(range[0], 'day')} 晚`
: '请选择日期范围'}
</Text>
</div>
)}
placeholder={['入住日期', '退房日期']}
suffixIcon={<CalendarOutlined />}
/>
</Card>
);
}
这个案例展示了如何使用RangePicker实现酒店预订的日期选择功能,包括禁用过去的日期、显示入住天数等功能。
2. 日程安排日历
import { Calendar, Badge, Popover } from 'antd';
import { ClockCircleOutlined, CoffeeOutlined, MeetingOutlined } from '@ant-design/icons';
import dayjs from 'dayjs';
// 模拟日程数据
const scheduleData = {
'2023-06-10': [
{ time: '09:00', title: '团队例会', type: 'meeting' },
{ time: '14:30', title: '项目评审', type: 'meeting' },
],
'2023-06-15': [
{ time: '10:00', title: '客户拜访', type: 'business' },
],
'2023-06-20': [
{ time: '12:00', title: '午餐会议', type: 'lunch' },
{ time: '15:00', title: '技术分享', type: 'meeting' },
],
};
function ScheduleCalendar() {
const getEventIcon = (type) => {
switch (type) {
case 'meeting':
return <MeetingOutlined style={{ color: '#1890ff' }} />;
case 'business':
return <ClockCircleOutlined style={{ color: '#fa8c16' }} />;
case 'lunch':
return <CoffeeOutlined style={{ color: '#52c41a' }} />;
default:
return <ClockCircleOutlined />;
}
};
return (
<Calendar
cellRender={(current, today, info) => {
const dateStr = current.format('YYYY-MM-DD');
const events = scheduleData[dateStr];
if (events && events.length > 0) {
const content = (
<div>
{events.map((event, index) => (
<div key={index} style={{ marginBottom: '8px' }}>
<Badge status="processing" text={
<span>
{getEventIcon(event.type)}
<span style={{ marginLeft: '8px' }}>{event.time} {event.title}</span>
</span>
} />
</div>
))}
</div>
);
return (
<Popover content={content} placement="top" trigger="hover">
<div>
<span>{current.date()}</span>
<div style={{ marginTop: '4px' }}>
{events.slice(0, 2).map((event, index) => (
<div key={index} style={{ fontSize: '12px', color: '#1890ff', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
{event.title}
</div>
))}
{events.length > 2 && <div style={{ fontSize: '12px', color: '#999' }}>+{events.length - 2} 更多</div>}
</div>
</div>
</Popover>
);
}
return info.originNode;
}}
/>
);
}
这个案例展示了如何使用Calendar组件实现一个日程安排功能,包括自定义单元格显示、悬停查看详情等功能。
国际化配置
Ant Design的时间组件默认使用en-US语言,如需设置其他语言,可以使用ConfigProvider进行全局配置:
import { ConfigProvider, DatePicker, Calendar } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
function App() {
return (
<ConfigProvider locale={zhCN}>
<DatePicker />
<Calendar />
</ConfigProvider>
);
}
更多国际化配置细节可以参考ConfigProvider 国际化文档。
常见问题解决
1. 日期格式转换问题
使用dayjs可以轻松处理各种日期格式转换:
// 字符串转dayjs对象
const date = dayjs('2023-01-01', 'YYYY-MM-DD');
// dayjs对象转字符串
const dateStr = date.format('YYYY年MM月DD日');
2. 时间选择器国际化不生效
确保正确导入并配置了dayjs的locale:
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
3. 限制日期选择范围
使用disabledDate属性可以限制可选日期范围:
// 只允许选择今天之后7天内的日期
<DatePicker
disabledDate={(current) => {
const today = dayjs();
const sevenDaysLater = today.add(7, 'day');
return current < today.startOf('day') || current > sevenDaysLater.endOf('day');
}}
/>
4. 表单中的日期验证
在Form组件中使用日期选择器时,可以添加自定义验证规则:
<Form.Item
name="birthday"
label="出生日期"
rules={[
{ required: true, message: '请选择出生日期' },
{
validator: (_, value) => {
if (value && value > dayjs().subtract(18, 'year')) {
return Promise.reject('必须年满18周岁');
}
return Promise.resolve();
}
}
]}
>
<DatePicker format="YYYY-MM-DD" />
</Form.Item>
总结
Ant Design的时间组件提供了强大而灵活的日期和时间处理能力,无论是简单的日期选择还是复杂的日程安排,都能满足各种业务需求。通过本文的介绍,我们了解了DatePicker和Calendar组件的基本用法、核心功能和高级特性,以及如何在实际项目中应用这些组件。
要深入了解更多细节,可以查阅官方文档:
- DatePicker组件文档:components/date-picker/index.zh-CN.md
- Calendar组件文档:components/calendar/index.zh-CN.md
- 通用属性文档:docs/react/common-props.zh-CN.md
掌握这些时间组件的使用,将有助于我们构建更加用户友好和功能完善的企业级应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



