跳转到内容

日历 calendar

数据录入组件。三层同源:无头内核给出解剖与状态机,Vue 组件与自定义元素只是它的两层外壳,行为完全一致。

示例

基础用法

网格由作者照插槽里的 weeks / weekDays 自己渲染,组件一个节点都不替你生成

2026年8月
周一周二周三周四周五周六周日
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
选中:(未选)

区间选择

selection-mode=range:第一下落起点、第二下落终点,中间铺一条连续底色

2026年8月
周一周二周三周四周五周六周日
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
区间:(未选)

不可选的日子

isDateUnavailable 与 min / max 都只挡落值不挡聚焦:方向键照样走得过去

2026年8月
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
可选窗口 2026-08-05 ~ 2026-08-19,周末除外 · 选中:(未选)

格子里放内容

cell-trigger 的内容全由作者写,日号之外还能塞自己的标记

2026年8月
周一周二周三周四周五周六周日
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
选中:(未选)

产物

自定义元素<xh-calendar>
Vue 组件XhCalendarCell XhCalendarCellTrigger XhCalendarGrid XhCalendarGridBody XhCalendarGridHead XhCalendarHeader XhCalendarHeading XhCalendarNextTrigger XhCalendarPrevTrigger XhCalendarRoot XhCalendarWeekDay XhCalendarWeekRow
组合式函数useCalendar
状态机calendarMachine
皮肤@xihan-ui/styles/calendar.css

解剖

部件名即 data-part 属性值,也是皮肤的选择器。加粗的是必备部件,不渲染它组件不工作(Web Components 适配器会在诊断通道上报 wc.missing-part)。

data-scope="calendar"root · header · prev-trigger · next-trigger · heading · grid · grid-head · week-day · grid-body · week-row · cell · cell-trigger

Props

属性类型必填说明
valuestring | string[]选中值,ISO 串。给定即受控:cell 直读 prop,写只发 onValueChange 不落内部值。 单选写成裸串是简写,内部一律归一成数组。
defaultValuestring | string[]
selectionModeCalendarSelectionMode
focusedValuestring当前聚焦的那天,ISO 串;它同时决定展示哪个月。给定即受控。 缺省时退回首个选中值,再退回今天。
defaultFocusedValuestring
minstring可选范围下界(含当天),ISO 串。界外的日子转 aria-disabled,但仍可聚焦。
maxstring可选范围上界(含当天),ISO 串。
isDateUnavailable(value: string) => boolean作者给的不可用判定,收 ISO 串。返回真的日子与界外日子同等对待。
localestring决定周首日与月份/星期几的文案,默认 zh-CN。
timeZonestring判定「今天」与格式化文案用的时区,默认取宿主本地时区。
disabledboolean整张日历禁用:翻月按钮转原生 disabled,格子全转 aria-disabled,键盘与点击都不改值。
readOnlyboolean只读:翻月与移动焦点照常,只是选不动值。
weekdayFormatCalendarWeekdayFormat表头缩写粒度,默认 short。
fixedWeeksboolean恒渲染六行,默认按当月实际周数。开着能让翻月时网格高度不跳。
onValueChange(details: CalendarValueChangeDetails) => voidvalue 变化意图回调;受控时是唯一出口,非受控随内部写入一并通知。
onFocusedValueChange(details: CalendarFocusChangeDetails) => void聚焦日变化(方向键、翻页、点了邻月的日子都会发);受控时是唯一出口。

状态机

状态idle

事件VALUE.SET · CELL.SELECT · FOCUS.SET · HOVER.SET · HOVER.CLEAR

connect API

useCalendar 产出的对象。getXxxProps() 铺到对应部件的宿主元素上,其余是可读状态与操作入口。

成员类型说明
valuestring[]选中集合,ISO 串;形状不随模式变。
selectionModeCalendarSelectionMode
focusedValuestring生效的聚焦日(三路收口后的结果),恒非空。
visibleMonth{ year: number, month: number, startValue: string }展示月:年、月(1-12)、月首日 ISO。
weeksCalendarDay[][]日期矩阵,作者照它渲染 week-row / cell / cell-trigger。
weekDaysCalendarWeekDay[]七列表头,作者照它渲染 week-day。
headingLabelstring展示月的标题文案(如 2024年2月),作者写进 heading 部件。
disabledboolean
readOnlyboolean
isSelected(value: string) => boolean
isUnavailable(value: string) => boolean界外或作者判定不可用。禁用的日历下恒为真。
canGoPrevboolean上一月是否还有可看的日子(整张禁用或整月都在 min 之前即为假)。
canGoNextboolean
setValue(next: string[]) => void
select(value: string) => void
focus(value: string) => void改写聚焦日;跨月会连带换掉展示月。
goToPrevMonth() => void
goToNextMonth() => void
getRootProps() => T['element']
getHeaderProps() => T['element']
getPrevTriggerProps() => T['button']
getNextTriggerProps() => T['button']
getHeadingProps() => T['element']
getGridProps() => T['element']
getGridHeadProps() => T['element']
getWeekDayProps(props: CalendarWeekDayProps) => T['element']
getGridBodyProps() => T['element']
getWeekRowProps() => T['element']
getCellProps(props: CalendarCellProps) => T['element']
getCellTriggerProps(props: CalendarCellProps) => T['element']

键盘

规格出处:W3C APG

按键生效条件行为
Tab / Shift+Tabfocus outside the grid整张网格只占一个 Tab 位:焦点进入聚焦日那一格
ArrowLeftfocus in grid焦点前移一天;越过月首即翻到上一月并落在那一天
ArrowRightfocus in grid焦点后移一天;越过月末即翻到下一月并落在那一天
ArrowUpfocus in grid焦点上移一周(减七天),跨月照样翻页
ArrowDownfocus in grid焦点下移一周(加七天),跨月照样翻页
Homefocus in grid焦点移到本周第一天;周首日随 locale 变
Endfocus in grid焦点移到本周最后一天
PageUpfocus in grid退一个月,日号不变(月末日被目标月夹住:3 月 31 日退成 2 月 29 日)
PageDownfocus in grid进一个月,日号不变
Shift+PageUpfocus in grid退一年
Shift+PageDownfocus in grid进一年
Enter / Spacefocus in grid, 聚焦日可用且非只读选中聚焦日:单选替换、多选切换、区间先落起点再落终点

Released under The MIT License