原生js之实现一个日历弹出框
实现功能:
点击输入框,弹出选择日期,显示当前年月日,当前日期背景为蓝色,字体为白色。
再次点击输入框,日期选择框消失。
点击选中日期,弹出框消失,输入框显示选中日期。
功能拆解
1. 一个input框,绑定点击事件。
2. 一个前一个月按钮,点击显示前一个月的日期,一个下一个月的按钮,点击显示下一个月的日期。
3. 弹出框header部分默认显示当前年月日,选择时显示选择的年月日。body部分,展示日期天数。
日期表格渲染思路
getMultidimensionalArrayByDay 函数 接收一个当前年和一个当前月共两个参数。返回一个包含年月日的多维数组。
getDayNumsByMonth 函数 接收一个月份参数,返回当前月天数。
代码部分
html
<div class="date-box">
<input type="text" placeholder="请输入日期" class="date-input" />
<div class="date">
<div class="date-header">
<div class="pre-date"><<</div>
<div class="show-year-month"></div>
<div class="next-date">>></div>
</div>
<table class="date-table">
<thead>
<tr>
<th>一</th>
<th>二</th>
<th>三</th>
<th>四</th>
<th>五</th>
<th>六</th>
<th>日</th>
</tr>
</thead>
<tbody class="date-tbody"></tbody>
</table>
</div>
</div>
css部分
<style>
.date-box {
width: 280px;
height: 300px;
position: relative;
overflow: hidden;
color: #606266;
}
.date-box input {
width: 100%;
height: 32px;
box-shadow: 2px 2px 5px #eee;
border-radius: 4px;
border: 1px solid #eee;
box-sizing: border-box;
text-align: center;
outline: none;
}
.date-box .date {
width: 100%;
height: calc(100% - 40px);
box-shadow: 2px 2px 5px #ccc;
border-radius: 4px;
border: 1px solid #eee;
position: absolute;
left: 0;
top: 40px;
box-sizing: border-box;
display: none;
}
.date-box .date .date-header {
width: 100%;
height: 30px;
display: flex;
justify-content: space-around;
align-items: center;
}
.date-box .date-table {
width: 100%;
height: calc(100% - 30px);
}
.date-box .date-table tr td {
border-collapse: collapse;
}
.date-box .date-table thead {
width: 100%;
height: 30px;
}
.date-box .date-table thead tr {
width: 100%;
height: 100%;
}
.date-box .date-table tbody {
width: 100%;
height: calc(100% - 30px);
}
.date-box .date-table tbody tr {
text-align: center;
vertical-align: middle;
}
.date-box .date-table tbody tr td:hover {
color: #409eff;
}
</style>
js
let date = new Date()
let currentYear = date.getFullYear()
let currentMonth = date.getMonth()
let currentDate = date.getDate()
let setCurrentDateFlag = false
let selectDate = ''
$('.show-year-month').textContent = `${currentYear}年${currentMonth + 1}月`
$('.pre-date').onclick = function () {
currentMonth = currentMonth - 1
if (currentMonth < 0) {
currentMonth = 11
currentYear = currentYear - 1
}
$('.show-year-month').textContent = `${currentYear}年${currentMonth + 1}月`
setCurrentDateFlag = false
getMultidimensionalArrayByDay(currentYear, currentMonth)
}
$('.next-date').onclick = function () {
currentMonth = currentMonth + 1
if (currentMonth > 12) {
currentMonth = 1
currentYear = currentYear + 1
}
$('.show-year-month').textContent = `${currentYear}年${currentMonth + 1}月`
setCurrentDateFlag = false
getMultidimensionalArrayByDay(currentYear, currentMonth)
}
$('.date-input').onclick = function () {
if ($('.date').style.display == 'none' || !$('.date').style.display) {
$('.date').style.display = 'inline-block'
observeTdClick()
} else {
$('.date').style.display = 'none'
}
}
function getMultidimensionalArrayByDay(currentYear, currentMonth) {
let trList = Array.from($('.date-tbody').children)
if (trList && trList.length) {
trList.map(item => {
$('.date-tbody').removeChild(item)
})
}
let d = new Date(currentYear, currentMonth)
d.setDate(1)
let startDay = d.getDay()
let count = 0
let nextPreMonthCount = 0
let multidimensionalArray = []
for (let i = 0; i < 6; i++) {
let dayColumnList = new Array(7)
if (i === 0) {
for (let j = startDay - 1; j < dayColumnList.length; j++) {
dayColumnList[j] = ++count
}
} else {
for (let j = 0; j < dayColumnList.length; j++) {
count++
if (count > getDayNumsByMonth(d.getMonth())) {
dayColumnList[j] = ++nextPreMonthCount
} else {
dayColumnList[j] = count
}
}
}
multidimensionalArray.push(dayColumnList)
}
let preMonthDayNums = getDayNumsByMonth(d.getMonth() - 1)
for (let k = d.getDay() - 2; k >= 0; k--) {
multidimensionalArray[0][k] = preMonthDayNums--
}
let nextMonthNums = getDayNumsByMonth(d.getMonth() + 1)
let realCurrentYear = date.getFullYear()
let realCurrentMonth = date.getMonth()
for (let q = 0; q < multidimensionalArray.length; q++) {
let tr = document.createElement('tr')
let item = multidimensionalArray[q]
for (let m = 0; m < item.length; m++) {
let td = document.createElement('td')
td.textContent = item[m]
if (!setCurrentDateFlag && item[m] === currentDate && realCurrentYear === currentYear && realCurrentMonth === currentMonth) {
td.style.backgroundColor = 'blue'
td.style.color = 'white'
setCurrentDateFlag = true
}
tr.appendChild(td)
}
$('.date-tbody').appendChild(tr)
}
}
function getDayNumsByMonth(currentMonth) {
let d = new Date()
d.setMonth(currentMonth + 1)
d.setDate(0)
let dayNums = d.getDate()
return dayNums
}
function observeTdClick() {
let tdList = Array.from(document.getElementsByTagName('td'))
tdList.forEach(td => {
td.onclick = function () {
let day = td.textContent
selectDate = `${currentYear}-${currentMonth + 1}-${day}`
$('.date-input').value = selectDate
$('.date').style.display = 'none'
}
})
}
function $(selector) {
return document.querySelector(selector)
}
getMultidimensionalArrayByDay(currentYear, currentMonth)