
本文旨在解决 JavaScript 日历实现中常见的日期停滞问题,并提供一个可复用的动态日历组件。通过分析问题代码,找出错误原因,并提供一个基于 HTML 表格的完整解决方案,帮助开发者构建功能完善的日历应用。教程包含详细的代码示例、CSS 样式以及注意事项,确保读者能够理解并成功应用。
在 JavaScript 中创建日历看似简单,但往往会遇到各种问题,例如日期无法正确更新、月份切换出错等。 本文将分析一个实际的日历实现问题,并提供一个更健壮、可维护的解决方案。
问题分析
原始代码存在以下几个主要问题:
日期设置错误: date.setDate(15); 这行代码将日期固定为每月 15 号,导致日历无法显示其他日期。date 变量的错误使用: 在循环中,date +=
; 试图将 HTML 字符串附加到 date 对象上,导致类型错误。事件监听器中的 renderCalendar() 调用: 虽然事件监听器正确地更新了月份,但由于上述日期设置错误,日历仍然无法正确显示。
解决方案:基于 HTML 表格的动态日历
以下是一个使用 HTML 表格构建的动态日历的完整解决方案。 该方案避免了上述问题,并提供了更清晰的代码结构。
立即学习“Java免费学习笔记(深入)”;
1. HTML 结构
使用 HTML 表格来组织日历的日期显示。
| ⇦ | month - year | ⇨ | ||||
|---|---|---|---|---|---|---|
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 // 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) { 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) } }
代码解释:
setGridDays(movMonth = 0) 函数: 此函数负责生成日历的日期网格。 movMonth 参数用于切换月份,0 表示当前月份,-1 表示上个月,+1 表示下个月。日期计算: 代码使用 Date 对象进行日期计算,确保日期和月份的正确显示。事件处理: 通过事件监听器,实现了点击上个月、下个月按钮以及日期单元格的功能。样式控制: 使用 CSS 类来控制日历的样式,例如 clickMonth 用于标记非当前月份的日期,today 用于标记今天的日期。
注意事项
国际化: LANG 变量用于设置日历的语言环境。 可以根据需要修改此变量以支持不同的语言。样式定制: 可以根据需要修改 CSS 样式来定制日历的外观。错误处理: 在实际应用中,应该添加错误处理机制,以防止潜在的错误。
总结
本文提供了一个使用 JavaScript 构建动态日历的完整解决方案。 通过分析原始代码中的问题,并提供一个更健壮、可维护的解决方案,帮助开发者构建功能完善的日历应用。 该方案使用 HTML 表格来组织日期显示,并使用 JavaScript 代码实现动态功能,包括月份切换和日期选择。 通过遵循本文提供的步骤和注意事项,开发者可以轻松地创建一个自定义的日历组件。
以上就是JavaScript 实现动态日历:从问题到解决方案的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1574819.html
微信扫一扫
支付宝扫一扫