日期字段
概述
分段式日期输入组件。将日、月、年以及可选的时间段拆成可独立键盘编辑的分段,同时仍能以原生表单值提交。适用于追求快速输入的紧凑日期录入场景——出生日期、有效期,或任何需要按范围校验的单个日期。需要从日历弹层选择日期时,优先使用 SDatePicker;需要浏览日历网格时,使用 SCalendar。
用法
特性
- 🧩 分段输入——每个日期部分(日/月/年,可选的时/分/秒/上午下午)都是可独立编辑的分段
- ⌨️ 完整键盘编辑——方向键增减、键入填充数字、自动前进到下一分段、Backspace 删除、
Enter/失焦提交 - 🎚 受控 / 非受控——
v-model与defaultValue由useControllableState支撑,另支持update:placeholder - ⛓ 范围校验——
minValue/maxValue/isDateUnavailable驱动data-invalid+aria-invalid状态 - 🕐 粒度与时间——
granularity(day/hour/minute/second)、12/24 小时制hourCycle、dayPeriod分段 - 📝 原生表单——视觉隐藏输入(
name/required/min/max)随所属表单提交 ISO 值 - 🚫 禁用 / 只读——两者都渲染正确的
data-*/aria-*状态并阻止编辑 - 🧩 可扩展——
leading/trailing插槽以及ui.root/ui.input类覆盖,构建于 AriaDateFieldRoot/DateFieldInput之上
组件族系
SDateField——样式包装层,透传 props 给 Aria compact 并注入dateFieldVariants类DateFieldCompact(Aria)——由DateFieldRoot+ 逐分段DateFieldInput数据驱动组合;无样式使用时从@vean/aria/date-field导入DateFieldRoot/DateFieldInput(Aria)——状态所有者(分段、校验、隐藏输入)与单个可编辑分段
演示
基础
Value: Sun Apr 19 2026 00:00:00 GMT+0000 (Coordinated Universal Time)
含时间
Value: [object Object]
自定义样式
API
Aria 层
4DateField
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 应用于根元素的额外类名。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
ui | Partial<DateFieldUi> | — | 该组件的按槽类重写。 |
inputProps | DateFieldInputProps | — | 转发给输入元素的属性。 |
id | string | — | 同上。 |
granularity | Granularity | — | 翻译粒度。 |
hourCycle | HourCycle | — | 小时周期。 |
step | DateStep | — | 步骤。 |
hideTimeZone | boolean | — | 是否隐藏时区。 |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
modelValue | DateValue | — | 当前模型值。 |
defaultValue | DateValue | — | 默认值。 |
disabled | boolean | — | 该组件是否已禁用。 |
dir | Direction | — | 组件的阅读方向。 |
placeholder | DateValue | — | 占位符。 |
readonly | boolean | — | 该组件是否为只读。 |
locale | string | — | 语言环境。 |
defaultPlaceholder | DateValue | — | 默认占位符。 |
maxValue | DateValue | — | 最大值。 |
minValue | DateValue | — | 最小值。 |
isDateUnavailable | DateMatcher | — | 日期是否不可用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | DateValue | undefined | 当模型值发生变化时触发。 |
update:placeholder | DateValue | 当占位符值发生变化时触发。 |
DateFieldCompact
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
inputProps | DateFieldInputProps | — | 转发给输入元素的属性。 |
id | string | — | 同上。 |
granularity | Granularity | — | 翻译粒度。 |
hourCycle | HourCycle | — | 小时周期。 |
step | DateStep | — | 步骤。 |
hideTimeZone | boolean | — | 是否隐藏时区。 |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
modelValue | DateValue | — | 当前模型值。 |
defaultValue | DateValue | — | 默认值。 |
disabled | boolean | — | 该组件是否已禁用。 |
dir | Direction | — | 组件的阅读方向。 |
placeholder | DateValue | — | 占位符。 |
readonly | boolean | — | 该组件是否为只读。 |
locale | string | — | 语言环境。 |
defaultPlaceholder | DateValue | — | 默认占位符。 |
maxValue | DateValue | — | 最大值。 |
minValue | DateValue | — | 最小值。 |
isDateUnavailable | DateMatcher | — | 日期是否不可用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | DateValue | undefined | 当模型值发生变化时触发。 |
update:placeholder | DateValue | 当占位符值发生变化时触发。 |
DateFieldInput
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
part | SegmentPart | — | 部分。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
DateFieldRoot
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
id | string | — | 同上。 |
granularity | Granularity | — | 翻译粒度。 |
hourCycle | HourCycle | — | 小时周期。 |
step | DateStep | — | 步骤。 |
hideTimeZone | boolean | — | 是否隐藏时区。 |
name | string | — | 字段的名称。作为名称/值对的一部分,与其所属表单一同提交。 |
required | boolean | — | 当值为 `true` 时,表示用户必须先设置该值,所属表单才能提交。 |
modelValue | DateValue | — | 当前模型值。 |
defaultValue | DateValue | — | 默认值。 |
disabled | boolean | — | 该组件是否已禁用。 |
dir | Direction | — | 组件的阅读方向。 |
placeholder | DateValue | — | 占位符。 |
readonly | boolean | — | 该组件是否为只读。 |
locale | string | — | 语言环境。 |
defaultPlaceholder | DateValue | — | 默认占位符。 |
maxValue | DateValue | — | 最大值。 |
minValue | DateValue | — | 最小值。 |
isDateUnavailable | DateMatcher | — | 日期是否不可用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:modelValue | DateValue | undefined | 当模型值发生变化时触发。 |
update:placeholder | DateValue | 当占位符值发生变化时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
default | DateFieldRootSlotProps | — |
注意
架构与行业对标差异
DateFieldRoot 通过 useControllableState 持有值,用 Intl.DateTimeFormat formatter 推导分段布局,并经 isInvalid 完成校验。每个 DateFieldInput 绑定 useDateField 组合式——它实现 per-part 键盘逻辑(增减/输入/自动前进/删除),由 time-field 族共享。编辑时原地变更 segmentValues shallowRef;root 在全部段填满后提交组装出的 DateValue。分段式日期输入模式源自 reka-ui(Radix);各对标库的日期输入通常是纯文本框加选择弹层,而非分段形式。
| 能力 | VeanUI | Ant Design | Element Plus | Mantine | Naive UI | shadcn |
|---|---|---|---|---|---|---|
| Aria/styled 分离 | ✅ | — | — | — | — | — |
| 可编辑分段 | ✅ | — | — | — | — | — |
| 受控 / 非受控 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| 键盘增减 / 键入 | ✅ | — | — | — | — | — |
| 分段间自动前进 | ✅ | — | — | — | — | — |
| 范围校验 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
isDateUnavailable | ✅ | — | — | — | — | — |
| 粒度(分/秒) | ✅ | — | — | — | — | — |
12/24 小时制 dayPeriod | ✅ | — | — | — | — | — |
| 禁用 / 只读 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| 原生表单提交 | ✅ | ✅ | ✅ | ✅ | ✅ | — |
leading/trailing 插槽 | ✅ | — | — | — | — | — |
使用注意
- 每个分段一旦填满即被提交;删除最后一个数字会以
undefined触发update:modelValue。 defaultValue仅在挂载时读取——外部控制请使用v-model。- root 使用
role="group",每个可编辑分段role="spinbutton"并带aria-valuemin/aria-valuemax/aria-valuenow;请为字段补充aria-label,让读屏软件能播报整个控件。 - 表单提交依赖
name;required/min/max会反射到隐藏输入,但不执行自定义校验。 granularity="day"渲染type="date";时间粒度在隐藏输入上渲染type="datetime-local"。readonly与disabled不同:字段仍可聚焦可见,但阻止编辑。
常见问题
如何清空值?
在单数字分段上按 Backspace(双数字分段需按两次)会清空该段并以 undefined 触发 update:modelValue——请在父组件处理 undefined。随后分段回退到占位符样式。
如何限制可选范围?
传入 minValue/maxValue——值超出范围时字段标记自身 data-invalid(分段上还有 aria-invalid)。isDateUnavailable 接受谓词函数,用于任意排除规则。
如何使用 12 小时制?
传入 hourCycle={12}(或让 locale 决定)——小时段变为 1–12,并出现 dayPeriod(AM/PM)分段。方向键与 a/p 键可切换时段。
SDateField 与 SDatePicker 有什么区别?
SDateField 是纯分段输入、无弹层——适合快速键入与表单提交。SDatePicker 在 DateField 之外嵌入日历 Popover,用于可视化选择。
如何自定义外观?
用 ui.root/ui.input 做类覆盖,或用 leading/trailing 插槽在分段周围放置图标/单位。需要完全无样式控制时,从 @vean/aria/date-field 组合 DateFieldRoot/DateFieldInput。