如何创建带年份或十年视图的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
相关产品推荐
相关产品推荐

