原生 <input type="date"> 因浏览器兼容性差(Safari/Firefox 功能缺失)、样式不可控、移动端体验不佳,无法满足可重用需求;需用 date-fns 构建轻量核心逻辑,配合完整键盘导航、ARIA 属性及简洁配置接口实现一致、可控、可组合的日期选择器。

为什么原生 <input type="date"> 不够用
原生日期输入控件在 Chrome、Edge 上表现尚可,但在 Safari(尤其旧版本)和 Firefox 中要么不渲染日历弹窗,要么缺少关键功能(如禁用日期、自定义格式、中文 locale)。更麻烦的是,它无法统一控制样式,::-webkit-calendar-picker-indicator 这类伪元素兼容性差,且无法响应式适配移动端触摸操作。
所以“可重用”不是指简单封装一个 <input>,而是要提供一致行为、可控状态、可组合的 UI 接口。
用 date-fns + 原生 DOM 构建轻量核心逻辑
不引入 React/Vue 等框架时,最稳妥的做法是选一个专注日期计算的库,date-fns 比 moment.js 更轻、tree-shakable,且函数式设计天然适合封装独立逻辑。
-
format和parse处理显示/输入字符串与 Date 对象互转,注意指定 locale(如zhCN)才能正确显示“年/月/日” -
isBefore/isAfter/isWithinInterval判断禁用日期,比手写时间戳比较更安全(避免时区陷阱) - 不要用
new Date()直接构造——用户输入 "2023-01-01" 在 Safari 下可能解析为 12月31日(UTC 转本地时区偏差),必须用parse显式指定格式
DOM 结构必须支持键盘与焦点管理
一个真正可用的日期选择器,不能只靠鼠标点选。用户会按 Tab 进入、用方向键切换日期、回车确认、ESC 关闭——这些都依赖正确的 tabindex、role 和 aria- 属性。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
立即学习“前端免费学习笔记(深入)”;
- 外层容器加
role="dialog"并用aria-modal="true",配合aria-labelledby指向标题 - 日期网格中每个
<button>都要有tabindex="-1",打开时动态设为0,确保键盘顺序可控 - 按
PageUp/PageDown切换月份时,需重新聚焦到当月第一天对应按钮,否则焦点会丢失 - 别忘了
document.addEventListener('keydown', ...)捕获全局 ESC,并检查当前是否处于打开状态
暴露简洁但完整的配置接口
可重用的关键是“别人能快速理解怎么用”,而不是参数越多越专业。实际项目里最常改的就四件事:初始值、最小/最大日期、是否允许清空、点击外部是否关闭。
- 把
minDate和maxDate设为字符串(如"2023-01-01")或Date实例,内部统一用parseISO转换,避免调用方纠结格式 -
clearable: true时,右上角显示 × 按钮,点击后触发change事件并传null—— 注意事件对象里必须包含value字段,和有值时保持结构一致 - 默认禁用
click-outside-to-close,因为很多表单需要连续填写多个字段,意外点空白处关掉选择器反而打断流程
真正难的不是写完一个能点的日历,而是让 minDate 动态变化时,已选日期仍合法、月份视图自动跳转、禁用状态实时更新——这些边界情况,比样式更消耗调试时间。


















