前端UI组件【免费下载链接】react-big-calendargcal/outlook like calendar component项目地址https://gitcode.com/gh_mirrors/re/react-big-calendar点击查看免费下载本指南以 react-big-calendar 仓库中的 Addons 文档为核心系统讲解其唯一官方扩展插件——Drag and Drop拖拽与缩放的完整用法从 HOC 包装、事件移动/缩放回调、allDay 边界行为到外部元素拖入日历的高级能力。读完本文你将能够为任意基于 react-big-calendar 的日历接入可拖拽、可缩放的交互体验并正确处理移动端、行布局与跨资源等细节场景。什么是 Addons以及仓库中的唯一扩展在 react-big-calendar 项目中src/addons/目录承载着由社区贡献与维护的额外功能模块它们构建在核心Calendar组件之上为日历补充核心组件之外的交互能力。仓库内的 Addons 说明 明确指出Addons are community contributed and maintained additional functionality built on top of the corereact-big-calendar。当前仓库只有一个 Addon——Drag and Drop位于 src/addons/dragAndDrop/。它以高阶组件Higher-Order ComponentHOC的形式存在为日历事件增加两种核心交互拖拽移动move把事件从某个时间段拖到另一个时间段拖拽缩放resize拖动事件边缘的把手来调整事件的开始/结束时间。从源码结构看该 Addon 由以下文件构成分工明确文件职责withDragAndDrop.jsHOC 主入口包装 Calendar 并注入 DnD 能力index.js对外导出withDragAndDrop的默认入口EventWrapper.js包裹每个事件处理拖拽起点与缩放把手anchorEventContainerWrapper.js包裹时间网格中的事件容器处理时间列的移动/缩放计算WeekWrapper.js包裹周视图的行区域含 allDay 行与月视图行处理行式拖拽DnDContext.js通过 React Context 向各层包装器传递拖拽状态common.js共享工具accessor 包装、组件嵌套合并、事件时长计算styles.scss 与 styles.less拖拽预览、把手、拖动中事件等视觉样式快速接入用 HOC 包装 Calendar将日历升级为可拖拽版本只需三步导入 HOC、包装组件、加上样式。import { Calendar } from react-big-calendar import withDragAndDrop from react-big-calendar/lib/addons/dragAndDrop import react-big-calendar/lib/addons/dragAndDrop/styles.css const DnDCalendar withDragAndDrop(Calendar) /* ... */ return ( DnDCalendar localizer{myLocalizer} events{events} draggableAccessor{(event) true} / )withDragAndDrop接收核心Calendar组件并返回一个新的DnDCalendar组件。从 withDragAndDrop.js 的源码可以看到HOC 生成的DragAndDropCalendar类继承了Calendar的propTypes与defaultProps因此你原来传给Calendar的所有属性localizer、events、views、min/max、popup等都可以原样传给DnDCalendar。注意两点导入细节入口路径发布包中该模块的实际路径是react-big-calendar/lib/addons/dragAndDrop对应仓库源码 src/addons/dragAndDrop/index.js。样式必须引入拖拽预览、缩放把手、拖动时的事件半透明效果等视觉反馈全部由 Addon 的专属样式控制不引入样式会导致交互能用但看不见。样式引入的两种方式除了直接引入编译好的 CSS你还可以在 Sass/Less 工程中引用源码样式import react-big-calendar/lib/addons/dragAndDrop/styles; // if using DnD这与主样式表react-big-calendar/lib/styles.css的引入方式一致详见仓库根目录 README.md。也可以直接引用仓库源码样式文件如 styles.scss自行构建。禁用缩放能力HOC 默认开启事件缩放resizable默认为true见 withDragAndDrop.js 中的defaultProps。如果只想让事件可移动、不可缩放把resizable设为false即可DnDCalendar localizer{myLocalizer} events{events} draggableAccessor{(event) true} resizable{false} // 关闭缩放只保留移动 /HOC 新增的核心回调属性HOC 在保留 Calendar 原有属性的基础上新增了三个与移动/缩放直接相关的回调onEventDrop、onEventResize与onDragStart。当用户完成一次移动或缩放操作时这些回调会携带目标时间信息被触发。function onEventDrop({ event, start, end, allDay }) {...} function onEventResize({ event, start, end, allDay }) {...} // type 恒为 drop function onDragStart({ event, action, direction }) {...}onEventDrop事件被拖拽到新位置并松手后触发start/end为新的时间范围allDay表示是否落在 allDay 行头部全天区域onEventResize缩放操作结束后触发参数同样包含新时间范围。文档特别注明这里的type恒为droponDragStart拖拽或缩放动作一开始就触发action为move或resizedirection为缩放方向UP/DOWN/LEFT/RIGHT移动时为null。这些回调只是通知你用户想把事件放到哪里并不会自动修改事件数组。你需要在自己的状态管理代码里把回调返回的新时间写回事件对象。仓库中的官方示例 stories/demos/exampleCode/dnd.js 展示了标准写法const moveEvent useCallback( ({ event, start, end, isAllDay: droppedOnAllDaySlot false }) { const { allDay } event if (!allDay droppedOnAllDaySlot) { event.allDay true } if (allDay !droppedOnAllDaySlot) { event.allDay false } setMyEvents((prev) { const existing prev.find((ev) ev.id event.id) ?? {} const filtered prev.filter((ev) ev.id ! event.id) return [...filtered, { ...existing, start, end, allDay: event.allDay }] }) }, [setMyEvents] ) const resizeEvent useCallback( ({ event, start, end }) { setMyEvents((prev) { const existing prev.find((ev) ev.id event.id) ?? {} const filtered prev.filter((ev) ev.id ! event.id) return [...filtered, { ...existing, start, end }] }) }, [setMyEvents] ) /* ... */ DragAndDropCalendar defaultDate{defaultDate} defaultView{Views.MONTH} events{myEvents} localizer{localizer} onEventDrop{moveEvent} onEventResize{resizeEvent} popup resizable /示例中在moveEvent里根据是否落在 allDay 槽同步调整事件的allDay标记这正是官方推荐的在回调中处理边界情况的实践。回调背后的触发链源码级解读从 withDragAndDrop.js 源码可以看出完整的数据流用户按下事件或缩放把手EventWrapper调用draggable.onBeginAction(event, move | resize, direction)handleBeginAction把{ event, action, direction }写入 HOC 的 state并触发onDragStart拖动过程中WeekWrapper行区域或EventContainerWrapper时间列区域内的Selection实例实时计算新位置并渲染一个__isPreview: true的预览事件松手后handleInteractionEnd根据action分发move调用onEventDropresize调用onEventResize。其中EventWrapper的缩放把手实现见 EventWrapper.js有一个值得注意的细节当事件以type date即行/日期模式展示时渲染左右把手LEFT/RIGHT以type time时间列模式展示时渲染上下把手UP/DOWN。此外从handleStartDragging的注释可知DOM 中缩放把手的事件会冒泡到移动监听器因此代码通过检查目标元素是否带有rbc-addons-dnd-resize类来避免误触发移动。行布局中的移动与缩放两个必须了解的细节官方文档强调移动和缩放存在一些微妙之处subtlety直接关系到交互结果是否符合预期行row布局的出现场景某些情况下非 allDay 事件会以行的形式被横向渲染。这发生在两类场景中月视图Month中的所有事件日/周视图中跨多天multi-day的事件——除非设置了showMultiDayTimes。行布局下的时间处理规则当用户把非 allDay 事件拖入头部allDay区域或者因为事件处于行布局而进行横向缩放时事件的时间时分秒会被保留只改变日期。这一规则在 WeekWrapper.js 的handleMove中得到了印证// Adjust the dates, but maintain the times when moving let { start, duration } eventTimes(event, accessors, localizer) start localizer.merge(date, start) const end localizer.add(start, duration, milliseconds)即先读取事件原开始时间再用目标槽的日期与它合并localizer.merge(date, start)从而做到日期变化、时间不变。用allDay参数判断落点如果你关心这些边界情况可以在回调中检查allDay参数判断用户到底把事件拖到了行区域头部 allDay 行还是时间列区域从而决定如何处理事件的 allDay 标记与时间。仓库示例 stories/demos/exampleCode/dnd.js 正是这样做的。从样式与 DOM 结构上也可以佐证这两种布局的存在EventWrapper针对行式事件渲染rbc-addons-dnd-resize-ew-anchor左右把手cursor: ew-resize针对时间列事件渲染rbc-addons-dnd-resize-ns-anchor上下把手cursor: ns-resize详见 styles.scss。缩放把手anchor的呈现规则除了上述移动细节EventWrapper对缩放把手的渲染还有一条硬性规则对跨出当前组件范围的延续事件continuesPrior/continuesAfter不显示把手。源码注释说明了原因这发生在showMultiDayTimes开启时事件的中间段以及事件正好落在日历min/max边界时——此时缩放已无意义隐藏把手避免误导用户。从日历外部拖入事件onDropFromOutside 与 onDragOver除了在日历内部移动/缩放事件这个 Addon 还支持把日历之外的拖拽元素例如任务列表、待办项拖进日历从而创建新事件。这由另外两个回调控制function onDropFromOutside({ start, end, allDay }) {...} function onDragOver(DragEvent) {...}默认不响应外部拖拽未传入onDropFromOutside时日历对外部拖拽元素完全无响应传入onDropFromOutside后当可拖拽的 DOM 元素被放到日历上时该回调被触发参数为{ start, end, allDay }——即落点对应的时间范围与是否落在 allDay 区域。注意该回调参数中不含事件对象本身事件来自外部你需要自行把外部元素与时间范围组合成新事件onDragOver的门卫作用只传onDropFromOutside而不传onDragOver默认所有可拖拽元素都能落入日历同时传了onDragOver它成为放行与否的判别器。在onDragOver中调用event.preventDefault()表示允许放入不调用则不允许放入。也就是说onDragOver让你可以根据拖拽元素的类型、来源或业务条件精细控制什么能拖进来。拖入日历的源码实现外部拖拽由EventContainerWrapper时间列与WeekWrapper行区域中的Selection监听dropFromOutside/dragOverFromOutside事件实现。以时间列为例见 EventContainerWrapper.jshandleDropFromOutside通过slotMetrics.closestSlotFromPoint(point, bounds)把鼠标落点换算成最近的时间槽再调用onDropFromOutside({ start, end, allDay: false, resource })结束时间由_calculateDnDEnd计算优先按外部事件对象的时长eventTimes得出的duration推算若外部事件没有时长isNaN则默认持续到下一个时间槽slotMetrics.nextSlot(start)拖动过程中的预览通过dragFromOutsideItem返回的外部事件对象渲染见handleDragOverFromOutside。这解释了为什么在外部拖入场景中还会出现第三个属性dragFromOutsideItem它是一个函数返回当前被拖拽的外部元素所对应的事件对象用于在拖动过程中渲染预览块详见 withDragAndDrop.js 中的propTypes与示例 stories/demos/exampleCode/dndOutsideSource.js。可拖拽性 / 可缩放性的精细化控制HOC 提供两个 accessor 属性允许你按事件粒度决定哪个事件可拖、哪个事件可缩放draggableAccessor: (event) booleanresizableAccessor: (event) boolean在 EventWrapper.js 中isDraggable与isResizable的计算逻辑为const isDraggable draggableAccessor ? !!get(event, draggableAccessor) : true const isResizable resizable (resizableAccessor ? !!get(event, resizableAccessor) : true)即不传 accessor 时所有事件默认可拖/可缩放resizable仍受全局开关约束传了 accessor 后只有返回真值的事件才具备对应能力。不可拖拽的事件会直接原样渲染不做任何包装源码中if (!isDraggable) return children。注意draggableAccessor与resizableAccessor的defaultProps均为null因此默认行为是全量可拖可缩。若需要按事件禁用例如偶数索引事件可拖、奇数不可拖可以参考示例 stories/demos/exampleCode/dndOutsideSource.js 中的isDraggable用法。交互过程中的视觉反馈机制为了让拖拽过程可感知Addon 在拖动/缩放期间做了三件事均由 styles.scss 与各包装器协作完成当前事件半透明、其余事件淡化拖动开始时HOC 在根节点加上rbc-addons-dnd-is-dragging类见 withDragAndDrop.js 的clsx拼接样式层让除被拖事件外的其他事件透明度降为 0.5被拖事件本身rbc-addons-dnd-dragged-event透明隐藏实时预览拖动过程中渲染一个带rbc-addons-dnd-drag-preview类的占位事件EventContainerWrapper的renderContent使用TimeGridEvent渲染预览WeekWrapper使用EventRow渲染行式预览并实时更新其top/height/left/right自动滚动EventContainerWrapper.updateParentScroll在拖动接近时间列顶部/底部时会自动滚动父容器让拖拽能跨越可见区域。另外EventWrapper对预览事件做了特殊处理当event.__isPreview为真时直接原样渲染并附加 preview 类不再包裹拖拽逻辑避免预览块被二次包装见 EventWrapper.js。资源Resource场景下的拖拽当日历启用了资源分组resources时拖拽同样可用。从源码可以看到交互结束的回调会携带资源信息时间列EventContainerWrapper.handleInteractionEnd在onEnd中传入resourceId: resource行区域WeekWrapper.handleInteractionEnd在onEnd中传入resourceId与isAllDay。因此在onEventDrop/onEventResize回调中你可以通过event.sourceResource在EventWrapper.handleStartDragging中写入拖拽起点资源以及回调的resourceId参数实现跨资源移动后的归属更新。仓库中的资源拖拽示例见 stories/addons/dragAndDrop/resource.stories.js 与 stories/demos/exampleCode/dndresource.js。需要注意回调参数中的resourceId与isAllDay属于实现细节使用时建议以官方文档所列的公开签名{ event, start, end, allDay }为基准并结合源码验证。组件级自定义与访问器配置HOC 通过mergeComponents见 common.js将三个内部组件注入 Calendarthis.components mergeComponents(components, { eventWrapper: EventWrapper, eventContainerWrapper: EventContainerWrapper, weekWrapper: WeekWrapper, })如果日历原配置了同名componentsmergeComponents会用nest(...)把自定义组件与 Addon 包装器嵌套组合自定义组件在外层、Addon 包装器在内层保证双方都生效——这与 HOC 自身selectable的处理方式类似HOC 会把selectable强制设为ignoreEvents若原先为真值或false避免与拖拽的选区逻辑冲突见 withDragAndDrop.js。总结react-big-calendar 的 Drag and Drop Addon 是一个功能完整的 HOC 扩展覆盖了事件移动、事件缩放、外部元素拖入、按事件粒度控制可交互性四大能力。使用时请记住四个关键点引入 HOC 与样式withDragAndDrop(Calendar)生成新组件且必须引入styles.css或源码样式才能看到拖拽反馈回调只通知、不改数据在onEventDrop/onEventResize中把新时间写回事件数组并善用allDay参数处理行布局边界行布局规则月视图所有事件、日/周视图中跨天事件未开启showMultiDayTimes处于行布局横向拖拽/缩放只改日期、保留时间外部拖入的门卫逻辑onDropFromOutside决定响应外部拖拽onDragOver决定哪些元素允许落入通过preventDefault放行。深入阅读源码可以进一步验证上述行为HOC 状态机见 withDragAndDrop.js行/列两种布局的落点计算分别见 WeekWrapper.js 与 EventContainerWrapper.js把手渲染与可拖性判断见 EventWrapper.js样式定义见 styles.scss完整可运行示例见 stories/demos/exampleCode/dnd.js 与 stories/demos/exampleCode/dndOutsideSource.js。赞分享前端UI组件【免费下载链接】react-big-calendargcal/outlook like calendar component项目地址https://gitcode.com/gh_mirrors/re/react-big-calendar点击查看免费下载相关推荐Feishin拖拽功能终极指南atlaskit/pragmatic-drag-and-drop的完整应用Feishin拖拽功能终极指南atlaskit/pragmatic drag and drop的完整应用 Feishin作为一款现代化的自托管音乐播放器通桌面应用音视频前端Flet 拖放Drag and Drop实战指南用 Draggable 与 DragTarget 构建可交互的拖拽界面Flet 拖放Drag and Drop实战指南用 Draggable 与 DragTarget 构建可交互的拖拽界面 拖放是桌面与移动应用中最高频的交互前端跨平台桌面应用移动开发WebTorrent CLI核心功能解密为何它是命令行 torrent 工具的佼佼者WebTorrent CLI核心功能解密为何它是命令行 torrent 工具的佼佼者 WebTorrent CLI 是一款功能强大的命令行 torrent 客上一篇PHPStan 纯函数错误标识符 pureFunction.parameterByRef 全解析引用参数与纯度契约冲突下一篇golua实战3种方法实现Go函数与Lua虚拟机的高效通信创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
SocketTool调试实战:TCP/UDP链路、关键参数与避坑指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:56:38
Elsevier期刊Proof校对实战指南:从接收到上线的关键操作 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:56:38
机顶盒刷机全攻略:从拆机短接到系统启动的完整实操指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:56:38
C#上位机温室监控系统:串口Modbus通信与数据联动实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 7:12:35
ApiGo平台MCP接入AI办公:TaoToken统一Key配置与REST API联调大纲 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 7:12:28
Finagle MySQL 客户端核心指标全解析:连接池回滚、游标流与预编译语句缓存 后端RPC框架 【免费下载链接】finagle A fault tolerant, protocol-agnostic RPC system 项目地址: https://gitcode.com/gh_mirrors/fi/finagle 点击查看 免费下载 导读
本文聚焦 Finagle 的 MySQL 客户端(com.twitter.finagle.Mysql)在运… · 2026/9/25 7:11:58
Playnite 使用指南:把 Steam、Epic、GOG 的游戏收进同一个窗口 Playnite 使用指南:把 Steam、Epic、GOG 的游戏收进同一个窗口 【免费下载链接】Playnite Video game library manager with support for wide range of 3rd party libraries and game emulation support, providing one unified interface for your games. 项目地… · 2026/9/25 7:11:58
Atlas 300V 24G推理加速卡上部署YOLO模型全指南 有人问我,Atlas 300V 24G 是运算加速卡吗?我的回答是:“是,但它不是你想的那种运算加速卡。”这张卡经常出现在边缘计算、智慧安防、工业质检这类项目的清单里,配套的关键词往往是“Atlas 部署YOLO”。如果你正准备把手… · 2026/9/25 7:11:51
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37