FullCalendar React多日事件渲染自定义:中间日期误判有事件
问题:FullCalendar多日事件中间日期误判有事件的修复
需求:修改FullCalendar React组件的多日事件(3天及以上)渲染逻辑,在dayGridMonth初始视图下,仅在事件的起始日期和结束日期渲染事件,不渲染中间日期。
现有问题:即使renderEventContent在中间日期返回null,dateHasEvent仍判定该日期存在事件,导致日期单元格显示有事件标记(has-event类)但实际无内容。
现有代码
FullCalendar组件声明
<FullCalendar ref={calendarRef} plugins={[dayGridPlugin]} initialView="dayGridMonth" themeSystem="bootstrap" dayMaxEvents={0} direction={isRTL ? 'rtl' : 'ltr'} stickyHeaderDates={false} editable={false} selectable={false} selectMirror eventTimeFormat={eventTimeFormat} events={events} initialDate={new Date()} style={{ fontSize: '5px' }} headerToolbar={{ start: 'title', center: '', end: `today prev,next` }} buttonText={{ today: t('common:today'), month: t('common:month'), week: t('common:week'), day: t('common:day'), list: t('common:list') }} moreLinkDidMount={args => dateHasEvent(args)} eventContent={renderEventContent} />
dateHasEvent函数
const dateHasEvent = info => { const dayCell = info?.el?.closest('.fc-daygrid-day'); if (dayCell) { const datCellNumber = dayCell?.querySelector('.fc-daygrid-day-number'); if (datCellNumber) { datCellNumber?.classList?.add('has-event'); } const dayEvents = dayCell ?.querySelector('.fc-daygrid-day-events') ?.querySelector('.fc-daygrid-day-bottom'); if (dayEvents) { const dayEventsLink = dayEvents?.querySelector('a'); if (dayEventsLink) { dayCell?.addEventListener('mouseover', function () { let popOver = document?.querySelector('.fc-popover'); if (popOver) { popOver?.querySelector('.fc-popover-close').click(); } dayEventsLink?.click(); }); } dayEvents?.classList?.add('day-cell-events-removal'); } } };
renderEventContent函数
const renderEventContent = eventInfo => { if (!eventInfo.isEnd && !eventInfo.isStart) { return null; } return ( <> {eventInfo.isStart && eventInfo.isStart != eventInfo.isEnd && ( <div style={{ backgroundColor: 'green', padding: '5px 0px 5px 0px', borderRadius: '20px', textAlign: 'center', fontWeight: 'bold' }} > {eventInfo.event.title} </div> )} {eventInfo.isEnd && ( <div style={{ backgroundColor: 'red', padding: '5px 5px 5px 5px', borderRadius: '20px', textAlign: 'center', fontWeight: 'bold' }} > {eventInfo.event.title} </div> )} </> ); };
解决方案
问题根源在于moreLinkDidMount触发的dateHasEvent函数,只要日期关联了事件(哪怕是中间日期)就会添加has-event类并处理事件逻辑,忽略了该日期是否是事件的起止节点。
修改方案1:在dateHasEvent中判断是否为事件起止日期
修改dateHasEvent函数,先判断当前日期是否是事件的起始或结束日期,仅在符合条件时执行后续逻辑:
const dateHasEvent = info => { const event = info.event; const dayCell = info?.el?.closest('.fc-daygrid-day'); if (!dayCell) return; // 获取当前单元格的日期(格式化为YYYY-MM-DD) const cellDate = dayCell.dataset.date; const startDate = event.start.toISOString().split('T')[0]; const endDate = event.end.toISOString().split('T')[0]; // 如果是事件的中间日期,移除可能存在的has-event类并返回 if (cellDate !== startDate && cellDate !== endDate) { const datCellNumber = dayCell.querySelector('.fc-daygrid-day-number'); datCellNumber?.classList?.remove('has-event'); return; } // 原有的起止日期处理逻辑 const datCellNumber = dayCell.querySelector('.fc-daygrid-day-number'); if (datCellNumber) { datCellNumber.classList.add('has-event'); } const dayEvents = dayCell ?.querySelector('.fc-daygrid-day-events') ?.querySelector('.fc-daygrid-day-bottom'); if (dayEvents) { const dayEventsLink = dayEvents.querySelector('a'); if (dayEventsLink) { dayCell.addEventListener('mouseover', function () { const popOver = document.querySelector('.fc-popover'); if (popOver) { popOver.querySelector('.fc-popover-close').click(); } dayEventsLink.click(); }); } dayEvents.classList.add('day-cell-events-removal'); } };
修改方案2:在renderEventContent中控制单元格样式
另一种思路是将has-event类的添加/移除逻辑移到renderEventContent中,仅在渲染事件内容时添加类,中间日期直接移除类:
const renderEventContent = eventInfo => { const dayCell = eventInfo.el.closest('.fc-daygrid-day'); const datCellNumber = dayCell?.querySelector('.fc-daygrid-day-number'); if (!eventInfo.isEnd && !eventInfo.isStart) { // 中间日期:移除事件标记类 datCellNumber?.classList?.remove('has-event'); // 移除事件容器的自定义类 const dayEvents = dayCell?.querySelector('.fc-daygrid-day-events')?.querySelector('.fc-daygrid-day-bottom'); dayEvents?.classList?.remove('day-cell-events-removal'); return null; } // 起止日期:添加事件标记类 datCellNumber?.classList?.add('has-event'); // 添加事件容器的自定义类 const dayEvents = dayCell?.querySelector('.fc-daygrid-day-events')?.querySelector('.fc-daygrid-day-bottom'); dayEvents?.classList?.add('day-cell-events-removal'); // 绑定鼠标事件(如果需要) const dayEventsLink = dayEvents?.querySelector('a'); if (dayEventsLink) { dayCell.addEventListener('mouseover', function () { const popOver = document.querySelector('.fc-popover'); if (popOver) { popOver.querySelector('.fc-popover-close').click(); } dayEventsLink.click(); }); } return ( <> {eventInfo.isStart && eventInfo.isStart !== eventInfo.isEnd && ( <div style={{ backgroundColor: 'green', padding: '5px 0', borderRadius: '20px', textAlign: 'center', fontWeight: 'bold' }} > {eventInfo.event.title} </div> )} {eventInfo.isEnd && ( <div style={{ backgroundColor: 'red', padding: '5px', borderRadius: '20px', textAlign: 'center', fontWeight: 'bold' }} > {eventInfo.event.title} </div> )} </> ); };
使用方案2时,可以移除FullCalendar组件上的moreLinkDidMount属性,避免重复处理。
内容的提问来源于stack exchange,提问作者Lafi Odeh
相关产品推荐
相关产品推荐

