如何修正日历组件中上月最后几天的位置渲染错误?
问题描述
尝试在日历中渲染上月的最后几天,但这些日期并未显示在正确的方格中。理想状态下,周二方格应显示31号、周一方格显示30号,以此类推。请问该如何修改代码,使日期对应到正确的方格中?
代码片段
JavaScript
let nav = 0; const getCalendar = document.getElementById("calendar"); const weekDays = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ]; function nextButton() { document.getElementById("nextButton")?.addEventListener("click", () => { nav++; render(); }); } function backButton() { document.getElementById("backButton")?.addEventListener("click", () => { nav--; render(); }); } function render() { const dt = new Date(); if (nav !== 0) { dt.setMonth(new Date().getMonth() + nav); } const day = dt.getDate(); const month = dt.getMonth(); const year = dt.getFullYear(); const firstDayOfMonth = new Date(year, month, 1); const daysInMonth = new Date(year, month + 1, 0).getDate(); const lastDateOfLastMonth = new Date(year, month, 0).getDate(); const dateString = firstDayOfMonth.toLocaleString("en-us", { weekday: "long", year: "numeric", month: "numeric", day: "numeric", }); const getFirstDayMonth = dateString.split(", ")[0]; // Wednesday const days = weekDays.indexOf(getFirstDayMonth); ( document.getElementById("month-heading") ).innerText = `${dt.toLocaleDateString("en-us", { month: "long" })} ${year}`; getCalendar.innerHTML = ""; for (let i = 1; i <= days + daysInMonth; i++) { const square = document.createElement("div"); square.classList.add("day"); const addedDay = i - days; /** * if the index is greater than the first day of the month add text for numbers * * else add padding squares */ if (i > days) { square.innerText = addedDay; if (addedDay === day && nav === 0) { square.id = "currentDay"; } } else { // enter the last few days of last month here this is where i might be doing // something wrong square.innerText = lastDateOfLastMonth - i + 1; // square.classList.add("padding"); } getCalendar?.appendChild(square); } } nextButton(); backButton(); render();
CSS
/* CSS may differ from original */ body { font-family: sans-serif; } #header { margin-bottom: 1rem; } h1 { font-size: 1.2rem; } #weekdays, #calendar { display: grid; grid-template-columns: repeat(7, 6rem [col-start]); } .day, #weekdays > div { width: 6rem; } #weekdays > div { border-bottom: thin solid gray; border-top: thin solid gray; margin-bottom: 1rem; } .day { border: thin solid gray; height: 6rem; }
HTML
<div class="container"> <div class="calendar-body"> <div id="header"> <h1 id="month-heading"></h1> <div> <button id="backButton">Back</button> <button id="nextButton">Next</button> </div> </div> <div id="weekdays"> <div>Sunday</div> <div>Monday</div> <div>Tuesday</div> <div>Wednesday</div> <div>Thursday</div> <div>Friday</div> <div>Saturday</div> </div> <div id="calendar"></div> </div> </div>
解决方案
问题出在你计算上月日期的表达式上,当前的lastDateOfLastMonth - i + 1会让日期顺序颠倒。比如当月第一天是周三(days=3)、上月最后一天是31号时,i=1(周日)会显示31,i=2(周一)显示30,i=3(周二)显示29,和你需要的顺序完全相反。
修改else块中的日期计算逻辑,换成以下表达式即可:
square.innerText = lastDateOfLastMonth - days + i;
同时建议给上月日期添加样式类,方便区分:
square.classList.add("padding");
修改后的完整else块代码:
} else { square.innerText = lastDateOfLastMonth - days + i; square.classList.add("padding"); }
原理说明
days是当月第一天在weekDays中的索引(比如周三对应3),代表需要填充的上月日期数量。lastDateOfLastMonth - days得到上月需要显示的起始日期(比如31-3=28,加上i从1到3,就得到29、30、31)。- 加上
i后,就能按周日到周二的顺序依次显示29、30、31,完全匹配你的需求。
内容的提问来源于stack exchange,提问作者BARNOWL
相关产品推荐
相关产品推荐

