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

如何创建带年份或十年视图的React Aria DatePicker

React-Aria DatePicker 实现年份视图与十年视图

完全可以通过 React-Aria 的 Calendar 组件结合 useCalendar 钩子自定义实现年份视图和十年视图,以下是具体实现方案与示例代码:

年份视图实现

年份视图核心是展示当前年份的12个月份,并支持逐年切换。利用 useCalendar 管理日期状态,自定义渲染月份按钮并处理年份切换逻辑。

核心代码

import { useCalendar, Button, Calendar } from 'react-aria-components';

function YearView({ calendarProps }) {
  const { state } = useCalendar(calendarProps);
  const currentYear = state.visibleRange.start.getFullYear();
  
  // 生成当前年份的12个月份数据
  const months = Array.from({ length: 12 }, (_, index) => {
    const date = new Date(currentYear, index, 1);
    return {
      date,
      label: new Intl.DateTimeFormat('zh-CN', { month: 'long' }).format(date)
    };
  });

  return (
    <div className="year-view-container">
      {/* 年份切换栏 */}
      <div className="year-nav">
        <Button onClick={() => state.decrementVisibleRange('year')}>←</Button>
        <span className="current-year">{currentYear}</span>
        <Button onClick={() => state.incrementVisibleRange('year')}>→</Button>
      </div>
      {/* 月份网格 */}
      <div className="month-grid">
        {months.map(({ date, label }) => (
          <Button
            key={date.toISOString()}
            onClick={() => state.selectDate(date)}
            className="month-btn"
          >
            {label}
          </Button>
        ))}
      </div>
    </div>
  );
}

// 使用自定义年份视图的DatePicker
function YearPicker() {
  return (
    <Calendar>
      {(props) => <YearView calendarProps={props} />}
    </Calendar>
  );
}

配套样式(可选)

.year-view-container {
  padding: 8px;
}
.year-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
.current-year {
  font-size: 1.2rem;
  font-weight: 500;
}
.month-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.month-btn {
  padding: 12px 8px;
  border: none;
  border-radius: 4px;
  background-color: #f5f5f5;
  cursor: pointer;
  transition: background-color 0.2s;
}
.month-btn:hover {
  background-color: #e0e0e0;
}

十年视图实现

十年视图需要展示一个十年区间(如2020-2029),支持按十年切换。基于当前可见年份生成十年内的年份按钮,处理十年范围的切换逻辑。

核心代码

import { useCalendar, Button, Calendar } from 'react-aria-components';

function DecadeView({ calendarProps }) {
  const { state } = useCalendar(calendarProps);
  const currentYear = state.visibleRange.start.getFullYear();
  const startDecade = Math.floor(currentYear / 10) * 10;
  const endDecade = startDecade + 9;
  
  // 生成十年内的年份列表
  const years = Array.from({ length: 10 }, (_, index) => startDecade + index);

  return (
    <div className="decade-view-container">
      {/* 十年区间切换栏 */}
      <div className="decade-nav">
        <Button onClick={() => state.decrementVisibleRange('decade')}>←</Button>
        <span className="decade-range">{startDecade} - {endDecade}</span>
        <Button onClick={() => state.incrementVisibleRange('decade')}>→</Button>
      </div>
      {/* 年份网格 */}
      <div className="year-grid">
        {years.map(year => (
          <Button
            key={year}
            onClick={() => {
              // 切换到选中年份的视图
              state.setVisibleRange({
                start: new Date(year, 0, 1),
                end: new Date(year, 11, 31)
              });
            }}
            className="year-btn"
          >
            {year}
          </Button>
        ))}
      </div>
    </div>
  );
}

// 使用自定义十年视图的DatePicker
function DecadePicker() {
  return (
    <Calendar>
      {(props) => <DecadeView calendarProps={props} />}
    </Calendar>
  );
}

配套样式(可选)

.decade-view-container {
  padding: 8px;
}
.decade-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
.decade-range {
  font-size: 1.2rem;
  font-weight: 500;
}
.year-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}
.year-btn {
  padding: 12px 8px;
  border: none;
  border-radius: 4px;
  background-color: #f5f5f5;
  cursor: pointer;
  transition: background-color 0.2s;
}
.year-btn:hover {
  background-color: #e0e0e0;
}

多视图切换(可选)

如果需要在默认日视图、年份视图、十年视图之间切换,可以添加视图切换控件:

import { useState } from 'react';
import { useCalendar, Button, Calendar } from 'react-aria-components';

function MultiViewDatePicker() {
  const [activeView, setActiveView] = useState('day'); // 可选值:'day' | 'year' | 'decade'

  return (
    <div className="multi-view-picker">
      <Calendar>
        {(props) => {
          switch(activeView) {
            case 'year':
              return <YearView calendarProps={props} />;
            case 'decade':
              return <DecadeView calendarProps={props} />;
            default:
              return <Calendar.View {...props} />; // 默认日视图
          }
        }}
      </Calendar>
      {/* 视图切换按钮组 */}
      <div className="view-switcher">
        <Button onClick={() => setActiveView('day')}>日视图</Button>
        <Button onClick={() => setActiveView('year')}>年份视图</Button>
        <Button onClick={() => setActiveView('decade')}>十年视图</Button>
      </div>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 08:38:49