You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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定位到日历主体的内置类,实现折叠:

  1. 给DateCalendar添加动态类:
<DateCalendar
  // 原有props
  className={collapse ? '' : 'calendar-collapsed'}
  slots={{ /* 原有slot配置 */ }}
/>
  1. 在样式文件中添加隐藏规则:
/* 直接隐藏日历主体 */
.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:36:07