最近在产品业务开展中,碰到了有使用日历展示数据的需求,当即想起来了js常用案例——万年历的实现,这里做的相对简单,只需获取本月的日历展示出来即可,另加上下月份切换。
首先,我们先来看一下最终要实现的效果,即UI设计图:
(这里只讨论万年历展示的实现,业务数据展示已马赛克,请见谅~~)
在设计图中我们可以看出,首尾的灰色部分为上月和下月的相关日期补充,蓝色部分为本月日期展示。 到这里我们就整理一下思路:
1、本月第一天是周几。
2、今年是平年/闰年的判断(关系到二月份天数)。
3、本月第一天前存在多少空位,需要补充多少上月日期。
4、本月最后一天存在多少空位,需要补充多少下月日期。
5、处理好逻辑关系后,将处理完的日历信息进行渲染展示。
思路整理之后,那么我们只需要将我们的逻辑转换为代码:
<!-- 基础布局html(只展示结构,css样式可自行修改,这里不做赘述) -->
<div class="calendarInfo">
<h6 class="calendarTitle">
<div class="setImg">
<span>工作记录台</span>
<span id="btn_prevmonth">上一月</span>
<span id="btn_nextmonth">下一月</span>
</div>
</h6>
<ol>
<li>周一</li>
<li>周二</li>
<li>周三</li>
<li>周四</li>
<li>周五</li>
<li>周六</li>
<li>周日</li>
</ol>
<ul id="calendarInfo">
</ul>
</div>
对应js处理逻辑:
$(function () {
let defineDate = new Date();
let theYear = defineDate.getFullYear(); // 年
let theMonth = defineDate.getMonth(); // 月
let theDay = defineDate.getDate(); // 日
loadchart();
// 日历信息加载【参数:prev:上月 next:下月】
function loadchart(prev, next) {
if (prev != '') { // 上月切换
if (theMonth == 0) {
theYear = theYear - 1;
theMonth = 12;
theMonth = theMonth - 1;
} else {
theMonth = theMonth - 1;
}
}
if (next != '') { // 下月切换
if (theMonth < 11) {
theMonth = theMonth + 1;
} else {
theMonth = 0;
theYear = theYear + 1;
}
}
let saveTotalDays = [31, 28 + is_leap(theYear), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // 包含12个月总天数
let firstDay = new Date(theYear, theMonth, 1);
let firstDayWeek = firstDay.getDay(); // 当前月第一天为周几(0-周日,1-周一,以此类推)
// 判断指定年份是否为闰年(闰年2月为29天/平年2月为28天)
function is_leap(year) {
return (year % 100 == 0 ? res = (year % 400 == 0 ? 1 : 0) : res = (year % 4 == 0 ? 1 : 0));
}
let momatch = [7, 0, 1, 2, 3, 4, 5]; // 当前月的一号前面有多少空位
$('#calendarInfo').empty();
// 处理当前月日历展示
var calendarInfo = document.getElementById("calendarInfo");
for (i = parseInt(momatch[firstDayWeek]); i > 0; i--) { // 上月结余
var preDate = new Date(firstDay - i * 24 * 60 * 60 * 1000).getDate(); //前i天日期【核心】
calendarInfo.innerHTML += '<li>' + preDate + '</li>';
}
var isNowMonth = theMonth + 1, // 当前月份
isNowYear = theYear; // 当前年份
$.post(basepath + "xxxx", { // 此接口为业务数据获取,可忽略该请求
a: 'xxx'
}, function (data) {
var preAll = parseInt(saveTotalDays[theMonth] + momatch[firstDayWeek]); //当前月1号前面的空白个数+这个月总天数
var j = 0;
for (i = parseInt(momatch[firstDayWeek] + 1); i <= preAll; i++) {
if (i == (theDay + momatch[firstDayWeek])) {
// 判断是否是休班还是工作日 [此处主要展示日期号]
if (data[j].IsWorkDay == '0') {
calendarInfo.innerHTML += '<li>' + parseInt(i - momatch[firstDayWeek]) + '</li>';
} else {
calendarInfo.innerHTML += '<li>' + parseInt(i - momatch[firstDayWeek]) + '</li>';
}
} else {
if (data[j].IsWorkDay == '0') {
calendarInfo.innerHTML += '<li>' + parseInt(i - momatch[firstDayWeek]) + '</li>';
} else {
calendarInfo.innerHTML += '<li>' + parseInt(i - momatch[firstDayWeek]) + '</li>';
}
}
j = j + 1;
}
let nextMonth = 6 * 7 - preAll; // 需要补充下月展示的数量【6为数据展示6行,7为数据展示7列】
for (i = 1; i <= nextMonth; i++) { // 下月补充
calendarInfo.innerHTML += '<li>' + i + '</span></li>';
}
}, 'json');
}
// 点击上一个月
$('#btn_prevmonth').click(function () {
loadchart(true, '');
});
// 点击下一个月
$('#btn_nextmonth').click(function () {
loadchart('', true);
});
});