如何实现MUI DateCalendar自定义头部的内容折叠功能?
MUI DateCalendar 折叠功能实现方案
针对你在自定义DateCalendar时遇到的无法传递折叠状态的问题,以下是几种可行的实现方式:
方案1:重写layout Slot 实现条件渲染
DateCalendar的layout Slot负责整体布局结构,你可以通过重写该Slot,将头部与日历主体拆分,直接用collapse状态控制主体的显示/隐藏:
export const StaticCalendar: React.FC<CalendarProps> = props => { // 原有state和方法 const { defaultValue, displayToolbar, onChange, views, value, reduceAnimations, ...rest } = props; const [collapse, setCollapse] = React.useState(true); const handleCollapse = () => setCollapse(prevState => !prevState); const DownArrow = () => <KeyboardArrowDown sx={{ fontSize: 24 }} />; return ( <CalendarWrapper> <LocalizationProvider dateAdapter={AdapterDayjs}> <DateCalendar showDaysOutsideCurrentMonth value={value} defaultValue={defaultValue} views={views || ['year', 'month', 'day']} reduceAnimations={reduceAnimations} onChange={onChange} dayOfWeekFormatter={(_day, date) => (date as Dayjs).format('ddd')} slots={{ switchViewIcon: DownArrow, calendarHeader: args => ( <CustomHeader handleHeaderClick={handleCollapse} currentDate={value} collapse={collapse} onMonthChange={(value: unknown) => onChange(value)} {...args} /> ), // 重写layout Slot layout: ({ calendarHeader, children }) => ( <div> {calendarHeader} {/* 用collapse控制主体显示,可添加过渡动画优化体验 */} {collapse && ( <div style={{ transition: 'max-height 0.3s ease', maxHeight: collapse ? '500px' : '0' }}> {children} </div> )} </div> ) }} {...rest} /> </LocalizationProvider> </CalendarWrapper> ); };
layout参数中的calendarHeader是你自定义的头部组件,children对应日历的主体内容(月份切换栏、日期网格等),通过条件渲染即可实现折叠效果。
方案2:CSS类名控制显示/隐藏
无需修改Slot,直接通过动态类名结合CSS定位到日历主体的内置类,实现折叠:
- 给DateCalendar添加动态类:
<DateCalendar // 原有props className={collapse ? '' : 'calendar-collapsed'} slots={{ /* 原有slot配置 */ }} />
- 在样式文件中添加隐藏规则:
/* 直接隐藏日历主体 */ .calendar-collapsed .MuiCalendarView-root { display: none; } /* 带过渡动画的折叠效果 */ .calendar-collapsed .MuiCalendarView-root { max-height: 0; overflow: hidden; transition: max-height 0.3s ease-in-out; }
这种方式简单直接,适合不需要复杂交互的场景。
方案3:拆分头部与日历主体,外层控制显示
将自定义头部与DateCalendar主体分开渲染,完全脱离内置Slot的限制,用collapse状态控制日历主体的显示:
export const StaticCalendar: React.FC<CalendarProps> = props => { const { defaultValue, displayToolbar, onChange, views, value, reduceAnimations, ...rest } = props; const [collapse, setCollapse] = React.useState(true); const calendarRef = React.useRef<DateCalendar>(null); const handleCollapse = () => setCollapse(prevState => !prevState); const DownArrow = () => <KeyboardArrowDown sx={{ fontSize: 24 }} />; return ( <CalendarWrapper> <LocalizationProvider dateAdapter={AdapterDayjs}> {/* 单独渲染自定义头部 */} <CustomHeader handleHeaderClick={handleCollapse} currentDate={value} collapse={collapse} onMonthChange={(newValue) => onChange(newValue)} // 如果需要切换视图,通过ref调用日历的方法 onViewChange={(view) => calendarRef.current?.setView(view)} /> {/* 控制日历主体显示 */} {collapse && ( <DateCalendar ref={calendarRef} showDaysOutsideCurrentMonth value={value} defaultValue={defaultValue} views={views || ['year', 'month', 'day']} reduceAnimations={reduceAnimations} onChange={onChange} dayOfWeekFormatter={(_day, date) => (date as Dayjs).format('ddd')} slots={{ switchViewIcon: DownArrow, // 隐藏默认头部 calendarHeader: () => null }} {...rest} /> )} </LocalizationProvider> </CalendarWrapper> ); };
这种方式自由度最高,你可以完全控制头部与日历的交互逻辑,但需要手动处理视图切换等原本由内置头部负责的功能。
内容的提问来源于stack exchange,提问作者Cecilia Mermoz
相关产品推荐
相关产品推荐

