应使用 ISO 字符串构造日期:const firstDay = new Date(${year}-${String(month + 1).padStart(2, '0')}-01),再调用 getDay(),确保跨平台一致;上月补 firstWeekday 个日期,本月天数用 new Date(year, month + 1, 0).getDate() 获取,下月补数为 42 - totalDays - firstWeekday。

uni-app 中获取某月第一天是星期几,别直接 new Date(year, month, 1).getDay()
uni-app 在 H5 和小程序平台对 Date 构造函数的月份处理不一致:传 new Date(2024, 1, 1) 在微信小程序里可能被解析为 2024 年 2 月 1 日(正确),但在某些安卓 WebView 或旧版 H5 中可能出现偏移。更稳妥的方式是用标准时间戳归一化:
- 先构造合法 ISO 字符串:
const firstDay = new Date(`${year}-${String(month + 1).padStart(2, '0')}-01`) - 再调用
firstDay.getDay(),确保跨平台返回一致的星期索引(0=周日,1=周一…) - 注意:
month是 0 起始,但字符串拼接时必须 +1 后补零,否则2024-1-01在部分环境会被误读
渲染日历格子时,如何补齐上月/下月占位日期
核心是算出当月 1 号前空几格、月末后空几格。关键不是“加减天数”,而是按“星期”对齐:
- 假设
firstWeekday = firstDay.getDay()(0~6),则上月需补firstWeekday个日期(例如周日开始就补 0 个,周一就开始要补 1 个) - 本月总天数用
new Date(year, month + 1, 0).getDate()获取(利用“下月 0 号 = 本月最后一天”) - 下月补数 =
(42 - totalDays - firstWeekday)(日历固定 6 行 × 7 列 = 42 格) - 上月日期用
new Date(year, month, 0 - firstWeekday + i + 1)计算(i从 0 开始),避免跨年时手动判断
点击日期触发跳转或选中时,为什么 date.getFullYear() 返回 NaN
常见原因是把字符串日期(如 "2024-03-15")直接传给 new Date() 后没校验有效性。uni-app 的 onTap 回调里拿到的可能是拼接的 data-date 属性值,它未经解析:
- 务必先做有效性判断:
const d = new Date(dateStr); if (isNaN(d.getTime())) return; - 推荐统一用
dateStr.replace(/-/g, '/')转斜杠格式再构造,兼容性更好 - 选中逻辑建议存时间戳
+d而非字符串,避免后续比较时隐式转换出错 - 小程序里
data-属性值始终是字符串,哪怕你写:data-date="item.date",uni-app 编译后仍是字符串
在 onPullDownRefresh 中更新日历时,如何避免月份错乱
下拉刷新常配合当前显示月份变量(如 currentMonth),但用户可能正在看 2024 年 12 月,刷新后误退到 2025 年 1 月——因为没锁死上下文:
- 不要在
onPullDownRefresh里直接this.currentMonth++或重置为new Date().getMonth() - 刷新应只重新生成当月数据,保持
currentYear和currentMonth不变 - 如果需求是“刷新回到今天”,请显式赋值:
this.currentYear = now.getFullYear(); this.currentMonth = now.getMonth();,而不是依赖new Date()构造时机 - 真机调试时注意:iOS 微信开发者工具的
Date有时会缓存系统时间,重启工具可验证是否为环境问题
实际渲染中容易忽略的是:不同平台对 new Date('2024-03') 解析结果不同,有歧义的字符串必须补全日部分;还有就是日历组件滚动区域高度没设死,导致在某些安卓机型上 touchmove 事件穿透失效。这些细节比算法本身更影响体验。


















