DatePicker 日期选择器
import { DatePicker } from '@apollo-design/ui';2026-10-30 当前 API:动态内容使用
#cellRender="{ current, info }"、#panelRender="{ originPanel }"、#extraFooter="{ mode }"、#tagRender="scope";前缀、后缀、清除、区间分隔与预设分别使用同名具名槽。移除旧函数渲染 props、addon、无实际组件的 PurePanel 类型及 notification props;使用@select/其它原生 emits。@keydown只收到原生 KeyboardEvent,可直接 preventDefault();支持v-model:mode。只读输入按 ArrowDown 进入面板,方向键导航,Enter/Space 选值,Escape 返回。DOM refs 在挂载前/卸载后为 null。
输入或选择日期的控件。
视口宽度为 575px 及以下时,日期时间与区间的面板在视口内换行展示,保留全部日期格、时间列与确认操作;两个区间面板均可通过原生键盘选值。较宽视口继续并排展示。
何时使用
- 当用户需要输入一个日期,可以点击标准输入框,弹出日期面板进行选择;
- 需要在「日期 / 周 / 月 / 季度 / 年 / 时间」等粒度间切换时,用
picker指定; - 需要选择一段时间范围时,用
RangePicker。
引入
import { DatePicker, RangePicker } from '@apollo-design/ui';
代码演示
基本 #
五种选择粒度(日 / 周 / 月 / 季 / 年)由 picker 控制。
范围选择器 #
DatePicker.RangePicker(或具名导出的 RangePicker)用于选择一个日期范围。
禁用日期 #
disabledDate 按当前面板粒度拿到日期;示例禁用周六/周日,单值与范围版本都生效。
上下界 #
minDate / maxDate 同时限制可选日期与面板导航;越界日期以禁用态呈现。
日期时间 #
show-time 打开时间面板;format 决定输入框与 change 第二参的文本格式。
12 小时制与步长 #
use12Hours 增加上下午列;hourStep / minuteStep 控制时间列可选项的步长。
预设范围 #
presets 在面板左侧(范围版)提供常用区间;值可以是 dayjs 实例,也可以是返回实例的函数(懒求值)。
受控 #
v-model:value 控制值、v-model:open 控制面板开合;外部按钮可以直接设值、清空或打开面板。
格式化 #
format 控制输入框展示与 dateString;范围版可传一个格式给两端,或传二元组分别指定。
尺寸、状态与变体 #
size 控制输入框尺寸,status 提供 error/warning 状态,variant 切换 outlined / filled / borderless / underlined。
标签与输入属性 #
用 id 与原生 label for 关联输入框,aria-describedby 关联说明。范围选择器使用对象 id 分别标记两端。class/style/data-* 仍作用于选择器根。
Associate native labels with inputs using id and label for, and descriptions using aria-describedby. Object ids identify each range endpoint. class/style/data-* still target the selector root.
多选 #
multiple 允许选择多个日期(不支持时间/日期时间);maxTagCount="responsive" 让标签随宽度自适应折叠。
自定义单元格 #
cellRender 拿到 current、info.originNode 与面板类型;示例在每 7 天的格子右下角画一个提示圆点,其余仍返回原始节点。
需要确认 #
needConfirm 让面板显示“确定”按钮,只有点击确定后值才提交;适合需要二次确认的录入流程。
范围日期时间 #
范围选择器同样支持 show-time;两端分别选择日期与时间,format 决定输入框的展示格式。
自定义面板 #
panelRender 拿到原始面板节点与当前面板粒度,返回的节点会替换浮层内容;示例在面板外加了一层边框与提示。
弹层位置 #
placement 控制浮层相对输入框的落点;空间不足时仍会由触发器自动翻转。
允许空值 #
范围选择器用 allowEmpty 指定两端是否允许只选一端;示例要求结束日期必填。
组件 Token #
在 DatePicker 根元素上覆写 --apollo-date-picker-* CSS 变量即可定制组件样式,例如 --apollo-date-picker-active-border-color、--apollo-date-picker-hover-border-color、--apollo-date-picker-active-shadow、--apollo-date-picker-input-font-size、--apollo-date-picker-cell-hover-bg 与 --apollo-date-picker-presets-width。打开面板可观察单元格悬浮色。
禁用 #
DatePicker 的 disabled 接受布尔值;DatePicker.RangePicker 还支持 [boolean, boolean] 元组,用来只禁用范围中的某一端。示例同时展示完全禁用、带默认值的禁用状态以及单端禁用。
受控面板模式 #
mode 用于受控地指定面板粒度(date / month / year)。示例用 RadioGroup 修改 mode,并通过 @panel-change 记录面板切换结果、通过 @change 回显最终选择值。
区间内选择 #
@calendar-change 会在范围选择的中间过程触发,携带 info.range 标识当前选的是起点还是终点;disabled-date 的第二个参数 info.from 是已选的起点。示例把结束日期限制在起点前后 7 天内,并实时显示选择进度。
起止日期联动 #
两个独立的 DatePicker 通过 disabled-date 互相限制:开始日期不能晚于已选结束日期,结束日期不能早于已选开始日期。@change 回写 value,页面下方实时显示当前范围。
语义化结构样式 #
DatePicker 的 classNames / styles 提供 root、prefix、input、suffix 与 popup 语义槽,其中 popup 还可细分为 root / header / body / content / item / footer / container。示例用类名定制输入区与浮层,用 styles 定制输入文字与后缀颜色。
自定义后缀图标 #
通过 suffix-icon 传入 VNodeChild 可以替换默认日历图标;传入 null 则完全不渲染后缀图标。示例用 h(CalendarOutlined) 与 h(SmileOutlined) 构造图标节点,并保留第三种「无图标」形态。
可切换粒度 #
picker 支持 date、week、month、quarter、year 五种粒度。示例用 RadioGroup 绑定 picker,切换后 DatePicker 的输入格式、面板结构与 @change 返回的 dateString 都会随之变化。
时间选择 #
show-time 打开时间面板,format 控制输入框展示格式,disabled-time 返回 { disabledHours, disabledMinutes, disabledSeconds } 来禁用具体档位。示例仅允许选择 09:00 到 18:00,并通过 @change 显示最终值。
日期区间 #
DatePicker.RangePicker 同样支持 picker 粒度切换。示例在日期、周、月、年四种粒度间切换,@change 的第二个参数始终是长度为 2 的格式化字符串数组,便于直接展示区间结果。
API
单值 DatePicker
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
value(v-model:value) |
受控值。null 表示「受控且为空」 |
DateType | DateType[] | null |
—— |
| defaultValue | 非受控初始值 | 同上 | —— |
| picker | 选择器粒度 | 'time' | 'date' | 'week' | 'month' | 'quarter' | 'year' |
'date' |
| mode | 面板的当前视图粒度(受控时需自己处理 panelChange) |
'time' | 'date' | 'week' | 'month' | 'quarter' | 'year' | 'decade' |
—— |
| format | 格式。支持字符串 / 数组(多套解析格式)/ 掩码对象 / 函数 | DatePickerFormat |
由 picker 与语言包推导 |
| showTime | 显示时间选择。true 或配置对象(use12Hours / disabledTime / hideDisabledOptions …) |
boolean | SharedTimeProps |
—— |
| showWeek | 周选择器下显示周数 | boolean |
—— |
| showToday | 显示「今天」 | boolean |
true |
| showNow | 时间面板显示「此刻」 | boolean |
true |
open(v-model:open) |
受控开合。undefined = 非受控 |
boolean |
—— |
| defaultOpen | 非受控初始开合 | boolean |
false |
| needConfirm | 是否要点「确定」才提交。⚠️ 默认值取决于粒度:time / datetime 为 true,其余 false |
boolean |
见左 |
| multiple | 多选 | boolean |
false |
| order | multiple 时按日期排序 |
boolean |
true |
| presets | 快捷选项。value 支持函数(懒求值) |
ValueDate[] |
—— |
| disabledDate | 不可选日期 | (date, info) => boolean |
—— |
| minDate / maxDate | 可选范围的边界(静态日期,与上游一致) | DatePickerDate |
—— |
| placeholder | 占位符 | string |
由语言包给出 |
| locale | 语言包(与 ConfigProvider 的 locale.DatePicker 深合并) |
PickerLocale |
—— |
| size | 尺寸(未传走 ConfigProvider) |
'small' | 'medium' | 'middle' | 'large' |
—— |
| variant | 形态 | 'outlined' | 'borderless' | 'filled' | 'underlined' |
'outlined' |
| status | 校验状态。⚠️ 只加类名,不改 aria-invalid |
'error' | 'warning' |
—— |
| disabled | 禁用 | boolean |
false |
| inputReadOnly | 输入框只读(禁止键入,只能用面板选) | boolean |
false |
| allowClear | 允许清除。传对象可自定义图标 | boolean | { clearIcon } |
true |
| suffixIcon | 后缀图标 | VNodeChild |
日历图标 |
| prefix | 前缀(可放图标或文字) | VNodeChild |
—— |
| clearIcon | 清除图标(deprecated → allowClear.clearIcon) |
VNodeChild |
—— |
| popupClassName | 浮层类名(deprecated → classNames.popup) |
string |
—— |
| popupStyle | 浮层样式(deprecated → styles.popup) |
CSSProperties |
—— |
| dropdownClassName | 同 popupClassName(deprecated) |
string |
—— |
| placement | 浮层落点。未传时按方向取默认(LTR bottomLeft / RTL bottomRight) |
'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight' |
—— |
| popupAlign | 浮层的对齐偏移 | AlignType |
—— |
| builtinPlacements | 自定义落点表 | Record<string, AlignType> |
内置四个 |
| getPopupContainer | 浮层挂载容器 | (node) => HTMLElement |
document.body |
| transitionName | 浮层动效名 | string |
${rootPrefixCls}-slide-up |
| required | 原生 required(透传 input[required] 与 aria-required) |
boolean |
—— |
| name / autoComplete / id | 绑定原生 input;id 可与 label for 关联 |
string |
autoComplete: 'off' |
| tabIndex / tabindex | 原生输入框的 Tab 顺序;tabindex 可作为 Vue attr 传入 |
number |
—— |
| autoFocus | 挂载时聚焦第一个未禁用的输入框 | boolean |
false |
| prefixCls | 类名前缀。⚠️ 默认是 apollo-picker(不是 apollo-date-picker) |
string |
—— |
| class / style | 根节点原生 attrs(替代上游 className / rootClassName / style) |
string | array | object / CSSProperties |
—— |
| classNames / styles | 语义化类名 / 样式(4 个平铺 + 7 个嵌套 popup)。popup 允许 string(= popup.root)。classNames.root / styles.root 落选择器根元素(与原生 class / style 合并,原生胜) |
DatePickerSemanticAllType |
—— |
顶层时间配置
上游 PickerProps extends Omit<SharedTimeProps, 'format' | 'defaultValue'>(SinglePicker.d.ts)⇒
下面这组键是顶层 prop(不必塞进 showTime),与 showTime 在 getTimeProps 内部合并
(showTime 里的同名键胜)。它们对日期面板与时间面板都生效。
| Prop | 说明 | 类型 | 默认 |
|---|---|---|---|
| use12Hours | 12 小时制(时间列多一列上午下午) | boolean |
—— |
| showHour / showMinute / showSecond / showMillisecond | 显式开关某一列 | boolean |
全部按格式推导 |
| hourStep / minuteStep / secondStep / millisecondStep | 列内档位步长 | number |
1 / 1 / 1 / 100 |
| hideDisabledOptions | 为真时跳过禁用档位(而不是渲染成禁用态) | boolean |
false |
| disabledTime | 按天给出禁用的档位(disabledHours 等三个 legacy 键见「兼容性说明」) |
(date) => DisabledTimes |
—— |
| changeOnScroll | 时间列滚动时立即改值 | boolean |
false |
| defaultOpenValue | 无值时面板的锚定时刻(不写入值;点「确定」才会落值) | DatePickerDate |
—— |
事件
| 事件 | 说明 | 载荷 |
|---|---|---|
update:value |
v-model:value 通道 |
(date) |
change |
值变化(与 update:value 同时发) |
(date, dateString) |
calendarChange |
面板选中过程中每次变化(未提交也发) | (date, dateString, info),info.range / info.from |
ok |
点「确定」 | (date) |
openChange |
浮层开合 | (open, config?) |
update:open |
v-model:open 通道 |
(open) |
pickerValueChange |
面板浏览值变化 | (date, info),info.source 为 'reset' | 'panel' |
update:pickerValue |
v-model:pickerValue 通道 |
(date) |
panelChange |
面板粒度变化 | (value, mode) |
clear |
点清除按钮 | —— |
focus / blur |
焦点进出 | (event, info) |
invalid |
键入值非法 | (invalid) |
submit |
表单提交 | (event) |
keydown |
按键(deprecated onKeyDown 的通道) |
(event: KeyboardEvent) |
Slots
| 插槽 | 说明 | 参数 |
|---|---|---|
panelRender |
替代 panelRender prop |
{ originPanel } |
extraFooter |
替代 renderExtraFooter prop |
{ mode } |
cellRender |
替代 cellRender prop |
{ current, info } |
Expose
| 方法 | 说明 | 类型 |
|---|---|---|
focus |
聚焦输入框 | (options?: FocusOptions) => void |
blur |
失焦 | () => void |
nativeElement |
根节点 | HTMLDivElement |
RangePicker(与单值的差异)
| 参数 | 差异 |
|---|---|
value / defaultValue |
元组 [start, end]。⚠️ null 与 undefined 语义不同:null = 「清空该端」,undefined = 「尚未选」 |
placeholder |
元组 [string, string] |
id |
string | { start?: string; end?: string };字符串只绑定起点,对象分别绑定两端,不生成额外 id |
separator |
两端之间的分隔符。默认分隔符带 aria-hidden;自定义的会去掉它 |
allowEmpty |
允许某一端为空(boolean 或两端元组) |
disabled |
boolean 或两端元组。⚠️ 根类名 -disabled 只在两端都禁时加 |
showTime |
boolean | RangeTimeProps(disabledTime 多 range / info 两个参数) |
presets |
RangeValueDate[] |
onSelect |
deprecated,且只在 picker === 'time' 时生效 |
focus |
签名不同:(index?) => void,可指定聚焦哪一端 |
startInput / endInput |
两个原生输入框 |
原生属性落点
class、style、data-* 和原生鼠标事件留在选择器根。id、tabIndex / tabindex、name、required、autoComplete、autoFocus 以及 aria-* 绑定实际输入框;范围选择器的共享属性应用到两端。aria-invalid 由内部输入校验维护,aria-required 默认随 required,可显式覆盖。受控值、输入事件和 ref 由组件维护。
修复 F01 后,原先根上的输入 ARIA 和 Tab 顺序移到 input;请将针对这些属性的 DOM 查询指向 input。范围两端需要不同标签时使用对象 id 与两个 label for。
Theme
组件级 Token —— 45 个,全部落成 CSS 变量 --apollo-date-picker-*。
下表是
node tests/visual/debug/extract-date-picker-css.mjs --tokens的实测值 (antd 6.6.4 默认主题),不是推算。
| Token | 默认值 |
|---|---|
activeBg |
#ffffff |
activeBorderColor |
#1677ff |
activeShadow |
0 0 0 2px rgba(5,145,255,0.1) |
addonBg |
rgba(0,0,0,0.02) |
arrowPath |
path('M 0 8 A 4 4 0 0 0 2.828…') |
arrowPolygon |
polygon(1.6568542494923806px 100%, 50% 1.6568542494923806px, …) |
arrowShadowWidth |
8.970562748477143px |
cellActiveWithRangeBg |
#e6f4ff |
cellBgDisabled |
rgba(0,0,0,0.04) |
cellHeight |
24px |
cellHoverBg |
rgba(0,0,0,0.04) |
cellHoverWithRangeBg |
#cbe0fd |
cellRangeBorderColor |
#82b4f9 |
cellWidth |
36px |
errorActiveShadow |
0 0 0 2px rgba(255,38,5,0.06) |
hoverBg |
#ffffff |
hoverBorderColor |
#4096ff |
inputFontSize |
14px |
inputFontSizeLG |
16px |
inputFontSizeSM |
14px |
lineWidthFocus |
1px |
multipleItemBg |
rgba(0,0,0,0.06) |
multipleItemBorderColor |
transparent |
multipleItemBorderColorDisabled |
transparent |
multipleItemColorDisabled |
rgba(0,0,0,0.25) |
multipleItemHeight |
24px |
multipleItemHeightLG |
32px |
multipleItemHeightSM |
16px |
multipleSelectorBgDisabled |
rgba(0,0,0,0.04) |
paddingBlock |
4px |
paddingBlockLG |
7px |
paddingBlockSM |
0px |
paddingInline |
11px |
paddingInlineLG |
11px |
paddingInlineSM |
7px |
presetsMaxWidth |
200px |
presetsWidth |
120px |
textHeight |
40px |
timeCellHeight |
28px |
timeColumnHeight |
224px |
timeColumnWidth |
56px |
warningActiveShadow |
0 0 0 2px rgba(255,215,5,0.1) |
withoutTimeCellHeight |
66px |
zIndexPopup |
1050 |
INTERNAL_FIXED_ITEM_MARGIN |
2px —— 变量名是 --apollo-date-picker-internal_fixed_item_margin(带下划线) |
⚠️ 另有一个规则内声明的变量
--apollo-date-picker-affix-color(默认inherit, 错误 / 警告态被覆盖)—— 它不在prepareComponentToken的返回值里,而是写在 样式规则内部。详见README §4。
设计说明
类名前缀与 CSS 变量命名空间不同名
默认类名是 apollo-picker(上游 getPrefixCls('picker', …) 传的是字面量 'picker'),
而 CSS 变量是 --apollo-date-picker-*(由组件名 DatePicker 派生)。
两者不同名是上游行为,不是笔误 —— 自定义主题时别改错。
time-picker 与本组件共用一套样式
ant-picker 前缀被 date-picker 与 time-picker 共用(上游刻意如此)⇒ 本组件的样式里
含 time-picker 的规则。那是对的(同一组件族)。
静态 CSS 的一处已知差异
构建期解析出来的常量(padding 算式、activeShadow 模板串、cellHoverWithRangeBg 的
lighten(35) 等)在静态 CSS 里被内联成字面值 ⇒ 不随主色变化
(上游 cssinjs 会在运行时重算)。这是本仓「静态 CSS + CSS 变量」架构的固有差异,
不是 bug;影响面由 L6 的主题矩阵钉住。