
本文旨在解决 JavaScript 日历实现中常见的日期停滞问题,并提供一个可复用的动态日历组件。通过分析问题代码,找出错误原因,并提供一个基于 HTML 表格的完整解决方案,帮助开发者构建功能完善的日历应用。教程包含详细的代码示例、CSS 样式以及注意事项,确保读者能够理解并成功应用。
在 JavaScript 中创建日历看似简单,但往往会遇到各种问题,例如日期无法正确更新、月份切换出错等。 本文将分析一个实际的日历实现问题,并提供一个更健壮、可维护的解决方案。
原始代码存在以下几个主要问题:
以下是一个使用 HTML 表格构建的动态日历的完整解决方案。 该方案避免了上述问题,并提供了更清晰的代码结构。
立即学习“Java免费学习笔记(深入)”;
1. HTML 结构
使用 HTML 表格来组织日历的日期显示。
<table id="date-picker">
<thead>
<tr>
<th class="clickMonth">⇦</th>
<th colspan="5"> month - year </th>
<th class="clickMonth">⇨</th>
</tr>
</thead>
<tbody></tbody>
</table>2. CSS 样式
提供基本的 CSS 样式,使日历看起来更美观。
table {
border-collapse : collapse;
margin : 2em 1em;
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
cursor : pointer;
}
td,th {
padding : .2em .8em;
border : 1px solid darkblue;
text-align : center;
}
thead {
background : #0d3269a9;
color : #e4eefc;
text-align : center;
}
.clickMonth {
cursor : pointer;
}
tbody td.clickMonth {
background : #b0c4dea8;
color : grey;
}
.clickMonth:hover {
color : #c72734;
background : #dcd91491;
}
.clickedMonth {
color : yellow !important;
background : crimson !important;
}
table#date-picker > thead > tr > th:nth-of-type(2) {
text-transform: capitalize;
}
.today {
background: radial-gradient(circle at center, #a6deff 60%, whitesmoke 10%, whitesmoke);
}
tbody td:not(.clickMonth):hover {
color : darkblue;
font-weight: bold;
}3. JavaScript 代码
以下 JavaScript 代码实现了日历的动态功能,包括月份切换和日期选择。
const
LANG = 'en-US' // 'en-US' 'fr-FR'
, datPickPrev = document.querySelector('#date-picker > thead tr:nth-of-type(1) th:nth-of-type(1)')
, datPickNext = document.querySelector('#date-picker > thead tr:nth-of-type(1) th:nth-of-type(3)')
, datPick_M_Y = document.querySelector('#date-picker > thead tr:nth-of-type(1) th:nth-of-type(2)')
, datPickDays = document.querySelector('#date-picker > tbody')
, showMonthYear = dte => dte.toLocaleDateString(LANG, {month:'long', year:'numeric'}).replace(' de ',' ')
;
const now = new Date()
var curr_Y_M_d1 = new Date(now.getFullYear(),now.getMonth(),1 )
// init Head Days ----------------------------------------------------------------------------------------
let
newRow = document.querySelector('#date-picker > thead').insertRow()
, wDat = new Date(curr_Y_M_d1.getTime())
;
wDat.setDate(wDat.getDate() - wDat.getDay())
for (let c=0;c<7;++c) // set day list [Sun Mon Tue Wed Thu Fri Sat]
{
newRow.insertCell().textContent = wDat.toLocaleDateString(LANG, {weekday:'short'}) // narrow
wDat.setDate(wDat.getDate() +1)
}
for (let r=0;r<6;++r) // add day rows
datPickDays.appendChild( newRow.cloneNode(true) )
//--------------------------------------------------------------------------------------------------------
setGridDays()
datPickPrev.onclick =_=> // previous month
{
datPickPrev.classList.add('clickedMonth')
setGridDays(-1)
setTimeout(_=>{ datPickPrev.classList.remove('clickedMonth') }, 200) // click anim
}
datPickNext.onclick =_=> // next Month
{
datPickNext.classList.add('clickedMonth')
setGridDays(+1)
setTimeout(_=>{ datPickNext.classList.remove('clickedMonth')}, 200) // click anim
}
datPickDays.onclick = ({target : td_el}) => // previous or next month clicked on calanda day.
{
if (!td_el.matches('td')) return
if (!td_el.matches('td.clickMonth'))
{
let pickedDate = new Date(curr_Y_M_d1.getFullYear(), curr_Y_M_d1.getMonth(), +td_el.textContent )
console.clear()
console.log( 'pickedDate -->', pickedDate.toDateString(), '<--')
setTimeout(console.clear, 1500)
return
}
// else no return and do a mov month...
td_el.classList.add('clickedMonth' ) // pseudo anin start
if (parseInt(td_el.textContent) < 20) datPickNext.click() // do next month click
else datPickPrev.click() // do previous month click
setTimeout(_=>{ td_el.classList.remove('clickedMonth') }, 200) // pseudo anin end
}
function setGridDays(movMonth = 0)
{
curr_Y_M_d1.setMonth( curr_Y_M_d1.getMonth() + movMonth ) // changing month +-
let
cMonth = curr_Y_M_d1.getMonth()
, wDat = new Date(curr_Y_M_d1.getTime())
;
wDat.setDate(wDat.getDate() - wDat.getDay()) // set on 1st weekDay (sunday)
datPick_M_Y.textContent = showMonthYear(curr_Y_M_d1)
for (let r=0;r<6;++r)
for (let c=0;c<7;++c)
{
datPickDays.rows[r].cells[c].textContent = wDat.getDate() // day number on month
datPickDays.rows[r].cells[c].classList.toggle('clickMonth', (wDat.getMonth()!==cMonth))
datPickDays.rows[r].cells[c].classList.toggle('today', (wDat.toDateString()===now.toDateString()))
wDat.setDate(wDat.getDate() +1)
}
}代码解释:
本文提供了一个使用 JavaScript 构建动态日历的完整解决方案。 通过分析原始代码中的问题,并提供一个更健壮、可维护的解决方案,帮助开发者构建功能完善的日历应用。 该方案使用 HTML 表格来组织日期显示,并使用 JavaScript 代码实现动态功能,包括月份切换和日期选择。 通过遵循本文提供的步骤和注意事项,开发者可以轻松地创建一个自定义的日历组件。
以上就是JavaScript 实现动态日历:从问题到解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号