
本文介绍如何使用成熟 react 日历库(如 fullcalendar)快速实现具备点击选中、鼠标拖拽创建事件功能的周视图调度器,避免从零开发的复杂性与兼容性风险。
构建一个类似 Google Calendar 的交互式周视图日历(支持点击选中时间块、鼠标按住拖拽跨时段创建事件),若从零手写 DOM 事件监听、时间轴计算、时区处理、移动端适配及无障碍支持,不仅开发周期长,还极易出现边界 bug(如跨天拖拽偏移、缩放失准、React 状态同步异常等)。因此,强烈推荐基于经过生产验证的 React 日历库进行定制化集成。
✅ 推荐方案:FullCalendar + React
FullCalendar 是目前最成熟的开源日历解决方案,其 React 官方封装 @fullcalendar/react 提供了完整的 TypeScript 支持、声明式 API 和开箱即用的交互能力:
- ✅ 原生支持 select(点击拖拽选择时间范围)
- ✅ 内置 dayGridWeek / timeGridWeek 视图,精准渲染小时粒度
- ✅ 自动处理时区、滚动定位、键盘导航与屏幕阅读器兼容
- ✅ 可轻松扩展:添加自定义事件渲染、拖拽回调、保存逻辑等
示例:最小可运行周视图(带拖选功能)
// CalendarScheduler.tsx
import React from 'react';
import FullCalendar from '@fullcalendar/react';
import timeGridPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction';
const CalendarScheduler: React.FC = () => {
const handleDateSelect = (info: any) => {
console.log('Selected time range:', {
start: info.start.toISOString(),
end: info.end.toISOString(),
allDay: info.allDay,
});
// ? 此处可弹出表单创建事件,或直接调用 API 保存
};
return (
);
};
export default CalendarScheduler;? 关键配置说明: selectable={true} 是启用拖拽选择的前提; select 回调接收 start/end 时间对象(含时区信息),可直接用于创建事件; timeGridWeek 视图提供精确到分钟的时间轴,比 dayGridWeek 更贴近 Google Calendar 体验; 如需支持“点击单个时间段”(非拖拽),可结合 dateClick 事件补充逻辑。
⚠️ 注意事项与最佳实践
- 时区处理:FullCalendar 默认使用浏览器本地时区。若业务需统一服务端时区(如 UTC+8),建议通过 timeZone 属性显式指定,并确保后端时间字段为 ISO 8601 格式(含时区偏移);
- 性能优化:当事件量 > 500 条时,启用 eventSource 的函数式加载 + 虚拟滚动(需配合 @fullcalendar/resource-timegrid);
- 样式定制:通过 CSS 变量(如 --fc-event-bg-color)或 eventContent 渲染函数深度定制事件外观;
- 移动端适配:interactionPlugin 自动支持触摸长按模拟拖选,无需额外 polyfill。
✅ 替代方案简评
| 库 | 优势 | 局限 |
|---|---|---|
| react-big-calendar | 轻量、高度可定制、文档清晰 | 拖选逻辑需手动增强,周视图粒度较粗 |
| rsuite/calendar | 内置中文支持、UI 统一 | 社区生态较小,高级交互(如跨天拖拽)需自行补全 |
| 自研方案 | 完全可控 | 预估开发 ≥ 3 人周,维护成本高,难以覆盖 Edge Cases |
✨ 总结:对于生产级应用,优先选用 FullCalendar —— 它不是“黑盒”,而是将 90% 的日历底层复杂性封装为稳定接口,让你聚焦于业务逻辑(如权限控制、冲突检测、协同编辑)而非时间算法本身。从 npm install @fullcalendar/react @fullcalendar/timegrid @fullcalendar/interaction 开始,15 分钟即可跑通可交互周视图。










