最简单但兼容性差,现代浏览器原生支持,值必须为yyyy-mm格式(如"2024-03"),需设name属性,推荐用new date().toisostring().slice(0,7)动态生成。

用 <input type="month"> 最简单,但兼容性差
现代浏览器(Chrome、Edge、Firefox 57+、Safari 14.1+)原生支持 <input type="month">,它会自动渲染为带年份和月份选择器的控件,无需 JS 或额外库。
常见错误是直接写 <input type="month"> 却没设 value 格式——它的值必须是 YYYY-MM 形式(如 "2024-03"),否则提交时为空或被忽略。
- 必须设置
name属性,否则表单提交时该字段不会被发送 -
value建议用 JS 动态生成:例如new Date().toISOString().slice(0, 7)得到当前年月 - Safari 旧版本(
- 用户可手动输入非标准值(如
"2024-13"),后端必须做二次校验
需要兼容老浏览器?用 <select></select> 手动构建年月选项
当目标用户包含 IE、旧版 Safari 或企业内网环境时,<select></select> 是最稳妥的选择。关键不是“怎么列选项”,而是“怎么生成合理范围”。
典型场景是选“入职月份”或“账单周期”,一般不需要从 1900 年开始拉满。建议限制在近 10 年到未来 2 年之间,避免下拉过长。
- 月份选项固定为 12 项,但年份范围要动态计算:用 JS 生成
2022–2026这类区间,而非硬编码 - 默认选中项推荐设为当前月份:
<option value="2024-03" selected>2024 年 3 月</option> - 注意
value仍保持YYYY-MM格式,和原生type="month"后端处理逻辑一致,减少适配成本 - 如果页面 JS 失败,纯 HTML 的
<select></select>仍可手动选择,降级体验可控
min 和 max 在原生 month 输入中作用有限
虽然规范支持 min="2023-01" 和 max="2025-12",但实际效果因浏览器而异:Chrome 会禁用超范围选项,Safari 可能完全忽略,移动端键盘甚至不响应这些属性。
更可靠的做法是结合 JS 拦截非法输入 + 后端强校验。不要依赖前端限制防止越界。
- JS 监听
input或change事件,用正则/^\d{4}-(0[1-9]|1[0-2])$/初筛格式 - 对通过格式校验的值,再解析为
Date实例判断是否在业务允许范围内(比如不能选未来 3 个月之后的月份) -
setCustomValidity()可配合提示,但 iOS Safari 对month类型的自定义验证支持不稳定
后端接收时别假设格式一定合法
无论前端用哪种方式,HTTP 请求中的 month 字段值都可能被篡改、为空、或格式错误。Node.js、Python、PHP 等后端语言收到的只是字符串,没有“类型保障”。
最容易被忽略的是时区问题:用户本地选了 "2024-03",但服务端解析成日期时若用了 new Date("2024-03"),结果可能是 2024-02-29T16:00:00.000Z(UTC 时间),导致月份错位。
- 推荐统一用字符串截取或正则提取年、月:
value.split('-'),而非转Date实例 - 存储时明确字段语义:是“某年某月的第一天”?还是纯粹的年月标识?避免后续按日粒度查询出错
- 数据库字段类型优先选
CHAR(7)或TEXT存YYYY-MM,比用DATE类型少一层隐式转换风险
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











