html仅提供日历结构,交互与动态渲染需javascript实现;用new date()计算日期、tolocaledatestring()控制格式、dataset存储日期数据、事件委托处理点击。

HTML 本身不能“创建活动日历”——它只负责结构,事件交互、日期渲染、点击响应都得靠 JavaScript 实现。纯 HTML 只能写一个静态表格或列表,连“今天是几号”都算不出来。
用 <table> 手写月视图容易卡在日期对齐和跨月逻辑
<p>很多人想用 <code><table> 搞个日历格子,但很快发现:1 号不一定是周一、2 月天数不固定、跨月的空白格要填多少个很难算准。浏览器不会帮你补空格,<code>getDay() 返回的数字(0–6)还得手动映射成列位置。
- 别硬算:用
new Date(year, month, 1) 获取当月第一天,再调 .getDay() 算出前面要填几个 <td></td>
- 月末天数别写死:用
new Date(year, month + 1, 0).getDate() 拿当月总天数(利用“下个月第 0 天”就是本月最后一天的特性)
- 避免把年月拼成字符串再解析:比如
"2024-2-1" 在 Safari 可能解析失败,统一用 new Date(2024, 1, 1)(注意月份从 0 开始)
date.toLocaleDateString() 渲染日期时要注意语言环境和格式碎片
new Date(year, month, 1) 获取当月第一天,再调 .getDay() 算出前面要填几个 <td></td>
new Date(year, month + 1, 0).getDate() 拿当月总天数(利用“下个月第 0 天”就是本月最后一天的特性)"2024-2-1" 在 Safari 可能解析失败,统一用 new Date(2024, 1, 1)(注意月份从 0 开始)date.toLocaleDateString() 渲染日期时要注意语言环境和格式碎片直接 date.toString() 输出的是本地默认格式,不可控;用 toLocaleDateString('zh-CN', { day: 'numeric' }) 虽然能取日,但如果你要拼“2024年3月15日”,就得分别调三次:年、月、日,而且中文环境下 month: 'long' 出来是“三月”,不是“3月”。
- 显示数字月推荐
{ month: '2-digit' },配合parseInt()去掉前导零(否则是 "03") - 服务端传来的 ISO 字符串(如
"2024-03-15T08:00:00Z")用new Date(str)解析没问题,但 IE 不支持带 T 的格式,得先 replace 掉 T 或用Date.parse() - 不要依赖
date.toISOString().split('T')[0]截字符串——时区偏移会导致结果错一天
给日历单元格绑定点击事件,别用 onclick 属性写死
写 <td onclick="handleClick(2024,3,15)">15</td> 看似简单,实际埋雷:HTML 属性里不能直接传对象或函数,参数一多就难维护,动态重绘时还要重新绑定,事件委托才是正解。
立即学习“前端免费学习笔记(深入)”;
- 给整个日历容器(比如
<table id="calendar">)加一个 <code>addEventListener('click', e => {...}) - 在回调里用
e.target.closest('td')判断是否点中了格子,再从td.dataset.date或td.getAttribute('data-date')读预存的日期(比如data-date="2024-03-15") - 渲染时提前把日期塞进
dataset,比运行时从 DOM 文本里 parse 数字更可靠、更快
真正麻烦的从来不是画格子,而是怎么让“3月15日有会议”这个信息,在用户点进去时准确对应到那天的数据上——数据结构和 DOM 结构必须对齐,而这个对齐点,往往藏在 dataset 或事件冒泡路径里,不是靠 class 名或 innerText 能稳拿的。











