input[type="date"]的min/max必须严格为yyyy-mm-dd格式,否则被静默忽略;动态设置需用setattribute或dispatchevent触发重绘;联动时需同步处理清空逻辑。

input[type="date"] 的 min/max 必须是严格 YYYY-MM-DD 格式
浏览器对 min 和 max 属性极其敏感:写成 "2026-10-20" 可以,但 "2026/10/20"、"2026-10-20T00:00"、"2026-10-2"(缺零)都会被静默忽略——UI 不变、不报错、checkValidity() 却返回 false。
常见翻车点:
-
new Date().toISOString()直接赋值 → 得到"2026-10-20T00:56:33.123Z",必须用.slice(0, 10)或.split('T')[0] - 手拼字符串写成
"2026-10-2"→ 字符串比较时它大于"2026-10-20",导致范围逻辑反转 - 后端返回
"2026/10/20"或"20-10-2026"→ 浏览器直接当没看见
动态设置 min/max 不能只靠 .min = 'xxx'
在 Safari(尤其是 iOS ≤ 15.5)和部分旧版 Chrome 中,直接写 input.min = '2026-10-20' 不会刷新日历 UI,用户仍能点选超限日期。
可靠做法只有两种:
- 用
input.setAttribute('min', '2026-10-20')—— 强制触发 DOM 属性变更和控件重绘 - 或写
input.min = '2026-10-20'后,立即补一句input.dispatchEvent(new Event('input', { bubbles: true }))
如果当前 input.value 已超出新设的 max,浏览器不会自动清空,必须显式判断并重置:if (input.value && input.value > input.max) input.value = ''
联动起止日期时,min 清空逻辑常被漏掉
做“结束日期 ≥ 开始日期”联动时,只监听 start 的 change 并设 end.min = start.value 是不够的。
用户清空开始日期后,end.min 仍卡在旧值上,导致结束框完全不可用。必须同步处理清空:
- 监听
start的change:若start.value === '',则end.removeAttribute('min')或end.min = '' - 监听
end的change:若end.value && start.value && end.value ,应调用 <code>end.setCustomValidity('结束日期不能早于开始日期')并立刻end.reportValidity() - 移动端 Safari 对
change触发不稳定,建议额外监听blur做兜底校验
min/max 不防键盘输入,校验必须双端做
min 和 max 只限制日历面板可选范围,对键盘输入、粘贴、手动删除重输等行为完全不拦截。用户可以轻松输入 "2025-01-01" 到一个 max="2024-12-31" 的 input 中。
所以前端校验不能只靠属性:
- 提交前必须用 JS 检查
input.value是否落在[input.min, input.max]范围内(注意字符串比较在 YYYY-MM-DD 下是安全的) - 服务端必须重新验证,不能信任任何客户端传来的日期字符串
- 尤其要注意:用户可能绕过 UI,用 DevTools 直接改 DOM 属性或 value
最易被忽略的一点:日期联动中,start 和 end 的值都可能是空字符串 '',不是 null 或 undefined;所有比较前必须先判空,否则 '' 会返回 <code>true,引发误判。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











