动态日历年份切换时月份下拉框默认值异常问题求助
动态日历月份选择异常问题排查与修复
我正在开发一款可从谷歌日历获取事件的动态日历,目前已实现核心功能:
- 选择当前年份(如2024年)时,月份下拉框仅展示当前及之后月份
- 选择未来年份时展示全部月份,该逻辑运行正常
但存在关键问题:当查看未来年份中早于当前月份的月份(如2025年3月)时,切换回当前年份(2024年),月份下拉框应默认选中当前月份(7月)并更新日历渲染相关变量,但实际会选中下拉框中不存在的选项。调试数小时仍未解决,附上相关代码求助:
function populateMonths() { const selectMonth = document.getElementById('selectMonth'); const currentYear = new Date().getFullYear(); const currentMonth = new Date().getMonth(); const months = [ 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro' ]; selectMonth.innerHTML = ''; // Clear existing options let startMonth = 0; if (selectedYear === currentYear) { startMonth = currentMonth; // Show from current month onwards } console.log(`currentYear: ${currentYear}`); console.log(`currentMonth: ${currentMonth}`); console.log(`selectedYear: ${selectedYear}`); console.log(`selectedMonth: ${selectedMonth}`); console.log(`startMonth: ${startMonth}`); months.slice(startMonth).forEach((month, index) => { const monthIndex = startMonth + index; const option = document.createElement('option'); option.value = monthIndex; // Adjust value to reflect actual month index option.textContent = months[monthIndex]; selectMonth.appendChild(option); }); selectMonth.selectedIndex = selectedMonth - startMonth; console.log(`Final selectedIndex: ${selectMonth.selectedIndex}`); } function populateYears() { const selectYear = document.getElementById('selectYear'); const currentYear = new Date().getFullYear(); const yearsToShow = 3; // Number of years to show, starting from the current year selectYear.innerHTML = ''; // Clear existing options for (let i = 0; i < yearsToShow; i++) { const year = currentYear + i; const option = document.createElement('option'); option.value = year; option.textContent = year; selectYear.appendChild(option); } selectYear.value = selectedYear; } function changeMonth() { selectedMonth = parseInt(document.getElementById('selectMonth').value); renderCalendar(selectedYear, selectedMonth); } function changeYear() { selectedYear = parseInt(document.getElementById('selectYear').value); populateMonths(); renderCalendar(selectedYear, selectedMonth); } function renderCalendar(year, month) { const calendar = document.getElementById('calendar'); calendar.innerHTML = ''; const firstDayOfMonth = new Date(year, month, 1); const lastDayOfMonth = new Date(year, month + 1, 0); const daysInMonth = lastDayOfMonth.getDate(); const startingDay = firstDayOfMonth.getDay(); // 0 (Sunday) to 6 (Saturday) const daysOfWeek = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb']; // Create header row for days of the week for (let day = 0; day < 7; day++) { const cell = document.createElement('div'); cell.classList.add('cell', 'header-cell'); cell.textContent = daysOfWeek[day]; calendar.appendChild(cell); } // Create blank cells for the days before the first day of the month for (let i = 0; i < startingDay; i++) { const cell = document.createElement('div'); cell.classList.add('cell', 'empty-cell'); calendar.appendChild(cell); } // Create cells for each day in the month for (let i = 1; i <= daysInMonth; i++) { const date = new Date(year, month, i); const dateString = formatDate(date); // Format date to 'YYYY-MM-DD' const cell = document.createElement('div'); cell.classList.add('cell'); cell.textContent = i; const dayEvents = events.filter(event => event.date === dateString); if (isFullyBooked(dateString)) { cell.classList.add('booked'); cell.title = 'Totalmente reservado'; } else if (isHalfBooked(dayEvents)) { cell.classList.add('half-booked'); cell.title = 'Parcialmente reservado'; cell.addEventListener('mouseover', () => showAvailableHoursTooltip(cell, dayEvents)); cell.addEventListener('mouseout', hideTooltip); } else { cell.classList.add('available'); cell.title = 'Disponível'; } calendar.appendChild(cell); } }
问题原因
问题出在populateMonths函数设置selectedIndex的逻辑上:当从未来年份(比如2025年3月,此时selectedMonth为2)切换回当前年份(2024年,startMonth为6),计算selectedMonth - startMonth得到2-6=-4,这是一个无效的下拉框索引,导致选中不存在的选项。
修复方案
在populateMonths函数中添加判断,确保selectedMonth始终处于当前年份的可选月份范围内。如果不在范围内,将其重置为startMonth(当前年份的当前月份),再计算选中索引。
修复后的populateMonths函数:
function populateMonths() { const selectMonth = document.getElementById('selectMonth'); const currentYear = new Date().getFullYear(); const currentMonth = new Date().getMonth(); const months = [ 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro' ]; selectMonth.innerHTML = ''; // Clear existing options let startMonth = 0; if (selectedYear === currentYear) { startMonth = currentMonth; // Show from current month onwards } // 关键修复:确保选中的月份在可选范围内,否则重置为当前月份 if (selectedMonth < startMonth) { selectedMonth = startMonth; } console.log(`currentYear: ${currentYear}`); console.log(`currentMonth: ${currentMonth}`); console.log(`selectedYear: ${selectedYear}`); console.log(`selectedMonth: ${selectedMonth}`); console.log(`startMonth: ${startMonth}`); months.slice(startMonth).forEach((month, index) => { const monthIndex = startMonth + index; const option = document.createElement('option'); option.value = monthIndex; // Adjust value to reflect actual month index option.textContent = months[monthIndex]; selectMonth.appendChild(option); }); selectMonth.selectedIndex = selectedMonth - startMonth; console.log(`Final selectedIndex: ${selectMonth.selectedIndex}`); }
额外说明
- 添加的判断逻辑保证
selectedMonth始终是当前年份可选的月份,避免计算出无效索引 - 重置
selectedMonth后,后续renderCalendar调用也会使用正确的月份,确保日历渲染正常
内容的提问来源于stack exchange,提问作者Kripthonite
相关产品推荐
相关产品推荐

