原生 date input 校验能力有限,仅检查 YYYY-MM-DD 格式,不验证日期存在性、合理性及范围;需用正则匹配加手动逻辑校验,并注意 valueAsDate/valueAsNumber 行为不稳定。

date input 的原生校验能力有限,别指望它能拦住所有非法输入
HTML <input type="date"> 本身只校验格式是否符合 YYYY-MM-DD,不检查日期是否存在(比如 2023-02-30 会被浏览器自动修正为 2023-03-02),也不校验是否在合理范围内(如未来100年、负数年份)。用户手动清空后输入 2023-00-00 或 abcd,Chrome 和 Firefox 表现不一致——有的直接忽略,有的触发 valueAsNumber 为 NaN,但表单仍可能通过 checkValidity()。
用 JavaScript 配合 setCustomValidity() 做二次校验
必须监听 input 和 change 事件,对 input.value 做解析和验证。关键点:
-
input.value为空时,不要强行校验,留空是合法状态(除非加了required) - 用
new Date(input.value)解析后,检查isNaN(date.getTime())—— 注意:new Date("2023-02-30")不返回Invalid Date,而是转成有效日期,所以得反向比对 - 更可靠的方式是拆分字符串:
input.value.match(/^(\d{4})-(\d{2})-(\d{2})$/),再验证月份 1–12、日期是否超过当月最大天数(需考虑闰年) - 校验失败时调用
input.setCustomValidity("请输入有效日期"),成功时必须调用input.setCustomValidity("")清除错误
注意 valueAsDate 和 valueAsNumber 的陷阱
这两个属性看似方便,但行为不稳定:
-
input.valueAsDate对非法值(如"2023-00-00")返回null,但对"2023-13-01"可能返回一个错位的Date对象(如2024-01-01),不能直接信 -
input.valueAsNumber是毫秒时间戳,NaN表示无效,但同样无法区分"abc"和"2023-02-30"(后者可能返回合法数字) - 建议统一走字符串正则 + 手动日期逻辑,避免依赖这些“魔法属性”
兼容性与 fallback 方案不能少
IE 完全不支持 type="date",旧版 Safari 对 min/max 属性支持差。实际项目中:
立即学习“前端免费学习笔记(深入)”;
- 必须提供降级:
<input type="text" pattern="\d{4}-\d{2}-\d{2}" placeholder="YYYY-MM-DD">,并配相同 JS 校验逻辑 - 用
Modernizr.inputtypes.date或简单检测document.createElement('input').type === 'date'来判断是否启用原生控件 - 移动端 iOS Safari 的 date picker 会忽略
min/max,必须在提交前用 JS 再校验一次范围



















