如何通过Ref API实现FullCalendar自定义日期范围?
如何通过Ref API为FullCalendar实现自定义日期范围
完全可以通过FullCalendar的Ref API实现自定义日期范围控制,不用依赖visibleRange props(这正是你遇到无限循环的原因)。直接调用Calendar实例的setVisibleRange方法就能修改视图的日期范围,具体实现步骤如下:
1. 为日期输入框添加状态与触发逻辑
在CustomCalendarHeader组件中,添加状态存储起止日期,并实现范围应用函数:
const CustomCalendarHeader: React.FC<Props> = ({ calendarRef, currentDate, setCurrentDate, }) => { const ref = calendarRef.current!.getApi(); // 新增日期状态 const [startDate, setStartDate] = useState<string>(''); const [endDate, setEndDate] = useState<string>(''); // 原有按钮逻辑保持不变 const nextHandle = () => { ref.next(); }; const prevHandle = () => { ref.prev(); }; const todayHandle = () => { ref.today(); }; const dayHandle = () => { ref.changeView('resourceTimelineDay'); }; const weekHandle = () => { ref.changeView('resourceTimelineWeek'); }; // 自定义日期范围应用函数 const applyCustomRange = () => { if (startDate && endDate) { // FullCalendar的end日期是排他性的,需将结束日期+1天以包含目标日期 const adjustedEndDate = new Date(endDate); adjustedEndDate.setDate(adjustedEndDate.getDate() + 1); // 调用API设置可见范围 ref.setVisibleRange({ start: startDate, end: adjustedEndDate.toISOString().split('T')[0] }); } }; return ( <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', px: 2, mb: 5, }} > <Box sx={{ display: 'flex', alignItems: 'center', gap: 2, flexGrow: 0.3 }} > <Button variant="contained" onClick={dayHandle}> Day </Button> <Button variant="contained" onClick={weekHandle}> Week </Button> <Typography>Custom: </Typography> <TextField type="date" size="small" sx={{ maxWidth: '125px' }} value={startDate} onChange={(e) => setStartDate(e.target.value)} /> - <TextField type="date" size="small" sx={{ maxWidth: '125px' }} value={endDate} onChange={(e) => setEndDate(e.target.value)} /> {/* 添加应用按钮触发范围设置 */} <Button variant="outlined" onClick={applyCustomRange}> Apply </Button> </Box> <ButtonGroup color="primary" variant="contained" sx={{ display: 'flex', alignItems: 'center' }} > <Button onClick={prevHandle}>Prev</Button> <Button onClick={todayHandle}>Today</Button> <Button onClick={nextHandle}>Next</Button> </ButtonGroup> </Box> ); };
2. 移除日历组件中的visibleRange配置
由于已经通过Ref API直接控制视图范围,无需再绑定visibleRange props,彻底避免datesSet与setCurrentDate触发的无限循环:
<FullCalendar eventDrop={handleResizeOrRedropEvent} eventResize={handleResizeOrRedropEvent} droppable={true} eventReceive={handleEventReceive} viewDidMount={handleViewChange} ref={refCalendar as LegacyRef<FullCalendar> | undefined} nowIndicator dayMaxEvents timeZone="UTC" height="80vh" datesSet={(arg) => setCurrentDate(arg)} displayEventTime={false} eventClick={handleEventClick} eventsSet={handleEvents} weekends={true} editable={true} selectable={true} plugins={[resourceTimelinePlugin, interactionPlugin]} events={[dragEventRow, ...timeFrames]} resources={[dragEventRow, ...timeFrames].map((timeframe) => ({ id: `${timeframe.type}-${timeframe.title}`, title: timeframe.title, type: timeframe.type, ...('children' in timeframe && { children: timeframe.children, }), }))} resourceGroupField="type" resourceAreaWidth={'20%'} initialView="resourceTimeline" eventContent={renderEventContent} headerToolbar={{ left: '', center: 'title', right: '', }} />
核心说明
setVisibleRange是FullCalendar原生API方法,通过Ref调用不会触发组件重渲染循环- 注意FullCalendar的
end日期为排他性设置,若需包含目标结束日期,需将日期+1天 - 若需要自动应用范围,可将
applyCustomRange绑定到日期输入框的onChange事件(例如当两个日期都有值时自动触发)
内容的提问来源于stack exchange,提问作者user22592696
相关产品推荐
相关产品推荐

