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

Antd Calendar:点击年份强制触发月份选择及面板交互问题

解决Antd Calendar年份点击触发月份选择及面板月份交互问题

核心思路

别自己单独维护年月状态,Antd Calendar本身提供了mode(控制面板显示:月/年/十年)和value(选中日期)状态,结合onPanelChange和自定义头部渲染,就能搞定需求,还不会和组件内部状态冲突导致下拉打不开。

代码实现

import React, { useState, useEffect } from 'react';
import { Calendar } from 'antd';

const CustomCalendar = () => {
  const [selectedDate, setSelectedDate] = useState(new Date());
  const [panelMode, setPanelMode] = useState('month');

  // 面板切换时处理:点击年份直接切到月份选择
  const handlePanelChange = (newDate, newMode) => {
    setSelectedDate(newDate);
    if (newMode === 'year') {
      setPanelMode('month');
    } else {
      setPanelMode(newMode);
    }
  };

  // 自定义头部,替换默认月份显示为可点击下拉
  const renderHeader = ({ value: headerDate, onChange }) => {
    const year = headerDate.getFullYear();
    const currentMonth = headerDate.getMonth();
    const monthList = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];

    return (
      <div style={{ padding: '0 8px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        {/* 年份点击触发年份选择面板,选中后自动切回月份视图 */}
        <button
          type="button"
          onClick={() => setPanelMode(panelMode === 'year' ? 'month' : 'year')}
          style={{ border: 'none', background: 'transparent', cursor: 'pointer', fontSize: '14px' }}
        >
          {year}年
        </button>
        {/* 月份下拉选择,直接触发日期更新和数据请求 */}
        <select
          value={currentMonth}
          onChange={(e) => {
            const newMonth = parseInt(e.target.value);
            const newDate = new Date(year, newMonth, 1);
            onChange(newDate);
            fetchCalendarData(`${year}/${newMonth + 1}`);
          }}
          style={{ border: 'none', background: 'transparent', cursor: 'pointer', fontSize: '14px' }}
        >
          {monthList.map((monthText, idx) => (
            <option key={idx} value={idx}>{monthText}</option>
          ))}
        </select>
      </div>
    );
  };

  // 模拟根据年月获取日历数据的函数
  const fetchCalendarData = (yearMonth) => {
    console.log('请求日历数据:', yearMonth);
    // 替换成你的实际接口请求逻辑
  };

  // 选中日期变化时自动拉取对应年月的数据
  useEffect(() => {
    const year = selectedDate.getFullYear();
    const month = selectedDate.getMonth() + 1;
    fetchCalendarData(`${year}/${month}`);
  }, [selectedDate]);

  return (
    <Calendar
      value={selectedDate}
      mode={panelMode}
      onPanelChange={handlePanelChange}
      headerRender={renderHeader}
    />
  );
};

export default CustomCalendar;

关键说明

  • 状态统一管理:完全用组件自带的selectedDate和panelMode,避免自定义年月状态和组件内部状态打架,解决下拉打不开的问题。
  • 年份点击强制切月份:在handlePanelChange里判断,只要面板模式切到year,立刻改成month,实现点年份直接进月份选择面板。
  • 自定义月份交互:通过headerRender替换默认的月份显示,用select做下拉,点月份直接弹出选择列表,选中后更新日期并触发数据请求。
  • 数据触发时机:监听selectedDate变化,或者在月份选择的回调里直接调接口,保证年月一变就能拿到对应数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:57:19