用途
Date Input 是一种专为输入日期值设计的表单字段模式。它涵盖两种主要实现方式:原生 <input type="date"> 控件(渲染浏览器内置的日期选择器),以及使用掩码或分段字段的结构化文本输入(例如 MM/DD/YYYY 格式,日、月、年各段之间自动前进)。
Date Input 与 Date Picker 的区别在于:它聚焦于通过键盘直接输入日期值,而不是基于日历的可视化选择。对于输入已知日期(出生日期、有效期)的场景,日历视图会增加不必要的复杂度,此时 Date Input 是更优选择。
适用场景
- 已知的精确日期:出生日期、护照有效期、信用卡有效期。
- 历史日期:过去很久的事件或记录,用日历导航会很繁琐。
- 年龄或时长输入:用户知道确切日期,无需日历上下文。
- 高频数据录入:用户需要快速输入大量日期的表单,直接文本输入更高效。
- 出生日期:用户总是知道这个值,无需日历导航。
不适用场景
- 日程安排与预约:应使用 Date Picker 展示可用性和上下文。
- 相对日期选择:“下周一”“3 周后”——应使用自然语言或日期选择器。
- 日期范围:应使用 Date Range 组件。
- 用户需要查看周边日期时:日历视图更有帮助。
实现流程
- 在复制示例前,先确认该模式与问题和约束条件匹配。
- 从 references/pattern.md 中的结构和示例入手,然后选择最小的可行变体。
- 在叠加视觉打磨之前,先应用无障碍、性能和交互方面的防护措施。
- 使用测试指南验证键盘、屏幕阅读器、响应式和失败场景下的行为。
无障碍防护
键盘交互模式:
| 按键 | 操作 |
|---|---|
| Tab | 将焦点移到日期输入框或下一个分段 |
| Shift + Tab | 将焦点移到上一个输入框或分段 |
| 0–9 | 在原生输入框或当前分段中输入数字 |
| Arrow Up / Down | 在原生日期输入框中递增/递减日期值 |
| Arrow Left / Right | 在原生输入框中切换日期部分;手动导航分段 |
| Backspace | 清除当前分段值;若为空则移到上一个分段 |
| Delete | 清除当前分段但不移动焦点 |
性能防护
- 初始渲染:日期输入 < 50ms
- 分段自动前进:< 16ms(单帧)
- 日期校验:组装后的日期 < 5ms
- 错误显示:失焦后 < 150ms
- 内存占用:每个日期输入实例 < 3KB
常见错误
未定义日期格式
问题:未提示预期格式的输入框会导致用户出错,在国际化场景中尤为明显。
<!-- Bad: No format hint -->
<label for="dob">Date of birth</label>
<input type="text" id="dob" placeholder="Enter date" />
修复方法:始终在标签或帮助文本中说明格式。
<!-- Good -->
<label for="dob">Date of birth (MM/DD/YYYY)</label>
<input type="text" id="dob" inputmode="numeric" placeholder="MM/DD/YYYY" aria-describedby="dob-help" />
<p id="dob-help">Example: 01/15/1990</p>
独立校验各分段而未做交叉校验
问题:只检查日 ≤ 31、月 ≤ 12、年为 4 位数字,会漏掉 2 月 30 日或 4 月 31 日这类无效日期。
修复方法:始终将组装后的日期作为整体校验。
function validateDate(month, day, year) {
const date = new Date(year, month - 1, day);
return (
date.getFullYear() === Number(year) &&
date.getMonth() === Number(month) - 1 &&
date.getDate() === Number(day)
);
}
未处理原生日期输入的值格式
问题:<input type="date"> 无论显示区域设置如何,始终以 YYYY-MM-DD 存储值,但开发者常试图解析显示格式。
修复方法:始终从 input.value(ISO 格式)或 input.valueAsDate 读取。
// Good: read ISO value, format for display separately
const dateInput = document.getElementById('my-date');
const isoValue = dateInput.value; // "2026-03-12"
const dateObject = dateInput.valueAsDate; // Date object
相关模式
- https://uxpatterns.dev/patterns/forms/date-picker
- https://uxpatterns.dev/patterns/forms/date-range
- https://uxpatterns.dev/patterns/forms/text-field
完整实现细节、示例和测试说明见 references/pattern.md。
模式页面:https://uxpatterns.dev/patterns/forms/date-input