js写简单日历
目录
- 生成日历
- 绑定事件
- 代码部分
- 样式
生成日历
日历是按月展示的,要正确生成一个月的日历最重要的就2点:
- 知道每个月第一天是周几(weekDay)
- 知道这个月总共有多少天
明确这2点之后,剩下的就只需要从第一天对应的weekDay开始遍历遇到【周末】就换行。遍历完一个月就可以生成一个最简单的日历。js的Date对象恰好提供了API可以直接得到上面2个问题的结果;【代码链接】
在使用Date的API时有几点需要注意:
//在js的Date返回的月份的范围是:[0,11]
let month = new Date().getMonth();//month=5;表示是6月份;
//假设现在要获取真实时间:2022-11-5 的11月份的第一天是周几? 11月有多少天
let firstWeekDay = new Date(2022,11-1,1).getDay();//11月第一天是周几;范围是[0,6],周一到周六对应[1,6], 周末对应 0;
let monthDays = new Date(2022,11,0).getDate();//11月总共有多少天
上面展示日历的结构图:
在每个月的日历中,如果展示月份的第一天不是周一就填充上个月的日期;在日历结尾出,如果最后一天不是周周末就填充下个月的日期;如果展示的是系统时间的年月,就标记当前日期;
绑定事件
给年月的增减按钮都绑定一个点击事件,给2个输入年月的输入框绑定onchange事件监听数据变化,年月更改就刷新日历;对输入框的输入做了简单校验。
最开始直接用table样式比较丑陋,后来又花时间调整了样式,下图是最开始的样式:
代码部分
生成一个月的日历是日历的最主要的功能,但也是最容易完成的部分。上面提到过使用js可以很容易得到一个月的第一天的firstweekOfDay(周几),totalDays(月总共天数);
function produceCalender(totalDays,firstWeekDay){
var createCalender="";
for(var day = 1; day <= totalDays;){
createCalender+='<tr>';
for(var weekDay =1 ; weekDay <= 7 && day <= totalDays ;weekDay++){
if( day === 1 && weekDay < firstWeekDay ){
createCalender+='<td></td>';
}else{
createCalender+='<td>'+day+'</td>';
day++;
}
}
createCalender+='</tr>';
}
return createCalender;
}
以上是最核心的生成日历方法,在得到2个关键的参数之后就循环遍历组装table元素;这里只显示了本月的【1-最大日期】,没有展示上一个月,下一个月的日期也没有显示当前日期。把这个弄好之后想要什么功能可以自己在这个基础上逐个的往里面添加。
其他的部分就是增加按钮,输入框可以自己输入想要生成年月的日历;对输入框输入的年月做校验,对按钮和输入框添加事件响应用户操作。最重要也是最耗时的是调整样式,这个比较麻烦需要自己花时间慢慢调整,在调整完之后看到前后对比明显好看很多。这个日历还有一个缺点没有固定展示行数,如果一直狂按下面的年月增减按钮由于每个月展示行数不一样会导致按钮位置发生变化,当一直点的时候用起来不方便。
这里可以稍作修改,在遍历完需要展示的月份之后再用空标签补位。如果展示了下个月的日期就用下个月的日期占位。
function produceCalender(totalDays,firstWeekDay){
var createCalender="";
var curRow = 0;//当前展示总行数
var SHOW_MONTH_ROWS=6;//总共展示6行;
for(let day = 1; day <= totalDays;){
curRow++;
createCalender+='<tr>';
for(let weekDay =1 ; weekDay <= 7 && day <= totalDays ;weekDay++){
if( day === 1 && weekDay < firstWeekDay ){
createCalender+='<td></td>';
}else{
createCalender+='<td>'+day+'</td>';
day++;
}
}
createCalender+='</tr>';
}
//如果展示月份的行数不足就在这里补上;
while(curRow < SHOW_MONTH_ROWS){
curRow++;
createCalender+="<tr>";
for(let compWeekDay =1 ; compWeekDay <= 7;compWeekDay ++){
createCalender += "<td></td>";//这里用了空标签占位;
}
createCalender+="</tr>";
}
return createCalender;
}
样式
日历整体分为三部分:
头部是由一个外层div包裹住三个部分,外层div结构用flex布局,对齐方式是:justify-content:space-between
。中间展示【年,月】的部分是由一个外层div包裹。年,月分别用了一个div来包裹,包裹年月的div也是一个flex布局采用纵向排列。直接用h标签来控制字体大小,会导致结构失控。
日历主体部分是用的ul
列表结构来实现的,在使用ul
结构时首先要清除掉ul的默认样式:list-style:none
。每一个ul
也都采用flex布局,每一排的对齐方式:justify-content:space-between
。然后调整每个li
之间的间距,字体大小,字体样式。
日历尾部部分:采用一个div包裹住左右两边的2个小div结构。采用flex布局,对齐方式是:justify-content:space-between
。
代码链接
还没有评论,来说两句吧...