
本文将指导你如何使用 JavaScript 创建一个动态日历,该日历可以显示当前月份的日期,并允许用户导航到上个月和下个月。我们将通过分析常见问题,提供修复方案,并展示一个可运行的日历示例,帮助你理解日历的构建逻辑,并能够根据自身需求进行定制。
理解日历的构建原理
构建日历的核心在于理解日期对象(Date)的使用。我们需要获取当前月份的第一天是星期几,以及当前月份有多少天,然后才能正确地将日期填充到日历的网格中。
常见问题及解决方案
一个常见的问题是在渲染日历时,日期停留在某个固定值,无法正确地切换到其他日期或月份。这通常是由于在 renderCalendar 函数中错误地设置了 date 对象导致的。
错误示例:
立即学习“Java免费学习笔记(深入)”;
const date = new Date();const renderCalendar = () => { date.setDate(15); // 错误:将日期固定为 15 号 // ... 其他代码}
解决方案:
不要在 renderCalendar 函数中固定日期。在初始化时使用当前日期,并在切换月份时更新 date 对象。
const date = new Date(); // 初始化为当前日期const renderCalendar = () => { // 不要在这里设置固定日期 // ... 其他代码}document.querySelector(".prev").addEventListener("click", () => { date.setMonth(date.getMonth() - 1); renderCalendar();});document.querySelector(".next").addEventListener("click", () => { date.setMonth(date.getMonth() + 1); renderCalendar();});
完整的日历实现示例
下面是一个完整的日历实现示例,它使用了 HTML、CSS 和 JavaScript。
HTML (index.html):
| ⇦ | month - year | ⇨ | ||||
|---|---|---|---|---|---|---|
CSS (style.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; }
JavaScript (script.js):
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) } }
使用方法:
将以上代码分别保存为 index.html, style.css, 和 script.js 文件。确保 script.js 在 index.html 的 标签的末尾被引用。在浏览器中打开 index.html 文件。
关键代码解释:
setGridDays(movMonth = 0): 这个函数负责生成日历的日期网格。它接受一个可选参数 movMonth,用于指定月份的偏移量(-1 表示上个月,1 表示下个月,0 表示当前月份)。curr_Y_M_d1: 这是一个 Date 对象,始终指向当前显示的月份的第一天。wDat: 这是一个临时 Date 对象,用于计算日历网格中的每个日期。datPickDays.rows[r].cells[c].classList.toggle(‘today’, (wDat.toDateString()===now.toDateString())): 这行代码用于标记今天的日期。
注意事项和总结
时区问题: JavaScript 的 Date 对象受到时区的影响。在处理日期时,请注意时区问题,并根据需要进行调整。日期格式化: 可以使用 toLocaleDateString() 方法对日期进行格式化,以满足不同的显示需求。代码可维护性: 将日历的逻辑封装成函数,并使用清晰的变量名,可以提高代码的可读性和可维护性。
通过本教程,你应该能够理解如何使用 JavaScript 创建一个动态日历。你可以根据自己的需求修改和扩展这个示例,例如添加事件、自定义样式等。记住,理解 Date 对象是构建日历的关键。
以上就是使用 JavaScript 构建动态日历:一步步教程的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1574825.html
微信扫一扫
支付宝扫一扫