
本文介绍如何使用成熟 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 分钟即可跑通可交互周视图。