使用 JavaScript 构建动态日历:一步步教程

聖光之護
发布: 2025-09-04 18:19:15
原创
163人浏览过

使用 javascript 构建动态日历:一步步教程

本文将指导你如何使用 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。

一览AI编剧
一览AI编剧

创意生成+情节生成+脚本生成,AI编剧3步走,AI自动帮你搞定剧情!

一览AI编剧 87
查看详情 一览AI编剧

HTML (index.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>
登录后复制

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<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)
    }
  }
登录后复制

使用方法:

  1. 将以上代码分别保存为 index.html, style.css, 和 script.js 文件。
  2. 确保 script.js 在 index.html 的 <body> 标签的末尾被引用。
  3. 浏览器中打开 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 构建动态日历:一步步教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号