实现方法
使用现成的库(推荐)
react-datepicker: 轻量级、高度可定制,支持日期范围选择、多语言等。@mui/x-date-pickers: Material Design 风格的日历,集成日期/时间选择功能。react-big-calendar: 适合日程管理应用,支持月/周/日视图和拖拽事件。
自定义实现基础日历
jsx
import React, { useState } from 'react';
function Calendar() {
const [currentDate, setCurrentDate] = useState(new Date());
const renderDays = () => {
const days = [];
const firstDay = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
1
).getDay();
const daysInMonth = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
0
).getDate();
// 生成日历格子
for (let i = 0; i < firstDay; i++) {
days.push(<div key={`empty-${i}`} className="empty-cell"></div>);
}
for (let day = 1; day <= daysInMonth; day++) {
days.push(
<div key={day} className="day-cell" onClick={() => handleDateClick(day)}>
{day}
</div>
);
}
return days;
};
const handleDateClick = (day) => {
console.log(new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
day
));
};
return (
<div className="calendar">
<div className="header">
<button onClick={() => setCurrentDate(
new Date(currentDate.getFullYear(), currentDate.getMonth() - 1)
)}>Prev</button>
<h3>{currentDate.toLocaleString('default', { month: 'long', year: 'numeric' })}</h3>
<button onClick={() => setCurrentDate(
new Date(currentDate.getFullYear(), currentDate.getMonth() + 1)
)}>Next</button>
</div>
<div className="days-grid">
{['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map(day => (
<div key={day} className="day-header">{day}</div>
))}
{renderDays()}
</div>
</div>
);
}
关键功能扩展
日期选择逻辑
- 添加状态管理存储选中日期
- 高亮显示当前选中日期
- 添加禁用日期逻辑(如过去日期不可选)
样式优化
- 使用CSS Grid布局日历格子
- 添加hover和active状态样式
- 响应式设计适配移动端
高级功能
- 国际化支持(使用date-fns或moment.js处理本地化)
- 日期范围选择
- 自定义日期标记(如节假日特殊样式)
性能优化建议
- 使用React.memo避免不必要的重渲染
- 复杂日期计算使用useMemo缓存
- 大数据量时考虑虚拟滚动
注意事项
- 时区处理要统一(建议使用UTC)
- 日期格式转换注意浏览器兼容性
- 无障碍访问需添加ARIA标签和键盘导航