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

基于@mui/x-date-pickers自定义日期范围选择器:外部控制显示月份需求

自定义相邻月份日期范围选择器实现方案(基于MUI X DatePicker)

完全可以从组件外部控制@mui/x-date-pickers中DatePicker的显示月份,核心是利用组件的openTo属性结合父组件状态实现,同时通过监听月份切换事件维持两个日历的相邻关系。以下是具体实现案例:

核心思路

  1. 父组件维护两个状态变量,分别控制两个DatePicker的显示月份
  2. 通过openTo属性将状态绑定到对应DatePicker,实现外部控制
  3. 监听onMonthChange事件,当其中一个日历的月份切换时,自动同步另一个日历为相邻月份
  4. 日期选择后同步调整月份,确保始终保持相邻关系

代码实现

import { useState } from 'react';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import dayjs from 'dayjs';

const CustomDateRangePicker = () => {
  // 初始化:开始月为当前月,结束月为下一个月
  const [startMonth, setStartMonth] = useState(dayjs());
  const [endMonth, setEndMonth] = useState(dayjs().add(1, 'month'));
  const [startDate, setStartDate] = useState(null);
  const [endDate, setEndDate] = useState(null);

  // 开始日历切换月份时,同步结束日历为下一个月
  const handleStartMonthSwitch = (newMonth) => {
    setStartMonth(newMonth);
    setEndMonth(newMonth.add(1, 'month'));
  };

  // 结束日历切换月份时,同步开始日历为上一个月
  const handleEndMonthSwitch = (newMonth) => {
    setEndMonth(newMonth);
    setStartMonth(newMonth.subtract(1, 'month'));
  };

  // 选择开始日期后,更新结束月份为开始日期所在月的下一个月
  const handleStartDateSelect = (newDate) => {
    setStartDate(newDate);
    if (newDate) {
      setEndMonth(newDate.add(1, 'month'));
    }
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <div style={{ display: 'flex', gap: '24px' }}>
        <DatePicker
          label="开始日期"
          value={startDate}
          onChange={handleStartDateSelect}
          openTo={startMonth}
          onMonthChange={handleStartMonthSwitch}
          slotProps={{
            calendar: {
              // 可选:禁用晚于结束日期的选项
              shouldDisableDate: (date) => endDate && date.isAfter(endDate)
            }
          }}
        />
        <DatePicker
          label="结束日期"
          value={endDate}
          onChange={(newDate) => setEndDate(newDate)}
          openTo={endMonth}
          onMonthChange={handleEndMonthSwitch}
          slotProps={{
            calendar: {
              // 可选:禁用早于开始日期的选项
              shouldDisableDate: (date) => startDate && date.isBefore(startDate)
            }
          }}
        />
      </div>
    </LocalizationProvider>
  );
};

export default CustomDateRangePicker;

关键细节说明

  • openTo属性:这是外部控制日历显示月份的核心,直接传入dayjs对象即可指定打开时的月份
  • onMonthChange事件:捕获用户手动切换月份的操作,通过状态同步确保两个日历始终相邻
  • 日期联动处理:选择开始日期后自动调整结束月份,避免出现月份不相邻的情况
  • 边界处理:dayjs会自动处理跨年份的月份增减(比如12月加1个月自动转为下一年1月),无需额外逻辑

内容的提问来源于stack exchange,提问作者Shai Mahnai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 23:43:36