日历选择器
对于日期相关处理,JavaScript 提供了 Date 对象。
而对于比较 Date 对象的构造器有一个非常有意思的地方,那就是越界了之后,Date 会帮你自动校正日期。
Sun Apr 16 2017 13:25:50 GMT+0800 (中国标准时间) // 当前日期 4/16
new Date(2017, 4, 1)
Mon May 01 2017 00:00:00 GMT+0800 (中国标准时间) // 日期 5/1 日
接下来我们来看一看日期的自动修正。
new Date(2017, 3, 0)
Fri Mar 31 2017 00:00:00 GMT+0800 (中国标准时间) // 3 月 31 日
// 4 月份的第 0 日,就是 3 月份的最后一日
new Date(2017, 3, 1)
Sat Apr 01 2017 00:00:00 GMT+0800 (中国标准时间) // 4 月 1 日
new Date(2017, 4, 0)
// 5 月份的 0 日,就是 4 月份的最后一日
new Date(2017, 3, 31)
Mon May 01 2017 00:00:00 GMT+0800 (中国标准时间) // 5 月 1 日
4 月份只有 30 日, 当为 31 日的时候,变成了 5月份的 1 日
通过这些我们就可以获取当前月份的最后一天,以及上个月最后一天。
*{padding: 0;margin: 0;}
.field{
width: 300px;
margin: 20px auto;
font-size: 12px;
position: relative;
}
.field input{
width: 100%;
box-sizing: border-box;
outline: none;
}
.date-select{
background: #e8e8e8;
color: #fff;
cursor: pointer;
transition: all .8s;
position: absolute;
width: 100%;
z-index: 2;
display: none;
}
.date-select table{
width: 100%;
border-collapse: collapse;
text-align: center;
}
.date-select table caption:after{
content: '';
display: block;
clear: both;
}
.date-select table caption{
background: #999;
line-height: 20px;
}
.date-select table th{
background: #999;
}
.date-select table tr:first-child{
line-height: 30px;
}
.date-select table tr td{
border: 1px solid #f0f0f0;
}
.date-select table tr:not(:first-child){
line-height: 25px;
}
.date-select table caption span#prev-month{
float: left;
padding-left: 10px;
}
.date-select table caption span#next-month{
float: right;
padding-right: 10px;
}
const prevMonthBtn = document.querySelector('#prev-month'),
nextMonthBtn = document.querySelector('#next-month');
const dateInput = document.querySelector('#date-input');
const dateSelect = document.querySelector('.date-select');
dateInput.onclick = () => {
if(dateSelect.style.display == "block" ){
dateSelect.style.display = "none";
return;
}
dateSelect.style.display = "block";
}
prevMonthBtn.onclick = () => {
console.log("prev");
}
nextMonthBtn.onclick = () => {
console.log("next");
}
解释都在注释里面,仔细看一下注释,然后自己运行一下,看看结果正确不正确。
接下来我们要把一些鼠标点击的事件,必须要等到已经渲染完HTML结构之后才能绑定,所以绑定的逻辑我们需要修改一下位置。
为了把当月的日期明显一点,我们增加一点样式
.date-select table tr td.current-month-day{
background: #d6d6d6;
}
function render(date){
let code = `
<table>
<caption>
<span id="prev-month"> < </span>
<small>${date.currentYear} - ${date.currentMonth}</small>
<span id="next-month"> > </span>
</caption>
<tbody>
<tr>
<th>一</th>
<th>二</th>
<th>三</th>
<th>四</th>
<th>五</th>
<th>六</th>
<th>日</th>
</tr>
<tr>
`;
date.dateArray.forEach((item, index) => {
if(index % 7 == 0) {
code += '</tr><tr>'
}
code += `<td class="${date.currentMonth == item.showMonth? 'current-month-day': ''}" data-index='${item.index}'>${item.showDate}</td>`
});
dateSelect.innerHTML = code;
const prevMonthBtn = document.querySelector('#prev-month'),
nextMonthBtn = document.querySelector('#next-month');
prevMonthBtn.onclick = () => {
let month = date.currentMonth - 1;
let year = date.currentYear;
let prevMonthDate = get42ArrayDate(year, month);
render(prevMonthDate); // 重新渲染数据
}
nextMonthBtn.onclick = () => {
let month = date.currentMonth + 1;
let year = date.currentYear;
let nextMonthDate = get42ArrayDate(year, month);
render(nextMonthDate); // 重新渲染数据
}
dateSelect.addEventListener('click', (e) => {
let targetDom = e.target;
console.dir(targetDom)
if(targetDom.tagName == 'SPAN' || targetDom.tagName != 'TD') return;
let selectDay = new Date(date.currentYear, date.currentMonth - 1, targetDom.dataset.index); // currentMonth是正常月份所以要减一
const inputValue = selectDay.getFullYear() + " - " + (selectDay.getMonth() + 1) + " - " + selectDay.getDate();
dateInput.value = inputValue;
dateSelect.style.display = "none"; // 隐藏选择框
},false)
}
let date = get42ArrayDate();
render(date);