如何实现日历仅为最新上一个点击元素添加Tailwind CSS阴影类?
日历点击状态异常问题
我用Tailwind CSS实现了一个日历,期望的点击状态逻辑是:
- 点击日期A:A添加
bg-pink-500、shadow-md、shadow-pink-500类 - 点击日期B:B添加上述完整类,A仅保留阴影类(
shadow-md、shadow-pink-500) - 点击日期C:C添加完整类,B仅保留阴影类,A清除所有额外类
但现在所有之前点击过的元素都会保留阴影类,不符合预期。以下是我的代码:
//select needed elements from HTML const calendarDates = document.querySelectorAll('.clickable') const dateDisplay = document.getElementById('show-details'); const selectedDateDayElement = document.getElementById('selected-date-day'); const selectedDateElement = document.getElementById('selected-date'); let latestClicked = null; let latestPreviouslyClicked = null; // if there is no date, dont add hover efects for (let i = 0; i < calendarDates.length; i++) { if (calendarDates[i].textContent.trim() === '') { calendarDates[i].classList.remove('hover:bg-pink-500', 'hover:shadow-md', 'hover:cursor-pointer', 'hover:shadow-pink-500'); calendarDates[i].classList.add('empty') } } // select only elements that are not empty const clickableDates = document.querySelectorAll('.clickable:not(.empty)'); clickableDates.forEach(dateElement => { dateElement.addEventListener('click', () => { const dateValue = dateElement.textContent.trim(); const year = 2017; const month = 1; if (latestClicked !== null) { latestPreviouslyClicked = latestClicked; latestClicked = null; latestPreviouslyClicked.classList.remove('bg-pink-500'); } dateElement.classList.add('bg-pink-500', 'shadow-md', 'shadow-pink-500'); latestClicked = dateElement; const selectedDate = new Date(year, month, parseInt(dateValue)); const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; const dayOfWeek = daysOfWeek[selectedDate.getDay()]; selectedDateDayElement.textContent = dayOfWeek; selectedDateElement.textContent = dateValue; dateDisplay.style.display = 'block'; }); }); // Close the date details when clicked outside, and this works at it should document.addEventListener('click', event => { if (!event.target.classList.contains('clickable')) { clickableDates.forEach(element => { element.classList.remove('bg-pink-500'); }); dateDisplay.style.display = 'none'; } });
修复代码
核心问题是只维护了最近两次点击的元素,没有处理更早的历史点击项。我们需要跟踪单条历史点击记录,每次点击时按规则清理状态:
//select needed elements from HTML const calendarDates = document.querySelectorAll('.clickable') const dateDisplay = document.getElementById('show-details'); const selectedDateDayElement = document.getElementById('selected-date-day'); const selectedDateElement = document.getElementById('selected-date'); let latestClicked = null; // 存储上一个点击的元素(仅保留一个历史阴影状态) let historyClicked = null; // if there is no date, dont add hover efects for (let i = 0; i < calendarDates.length; i++) { if (calendarDates[i].textContent.trim() === '') { calendarDates[i].classList.remove('hover:bg-pink-500', 'hover:shadow-md', 'hover:cursor-pointer', 'hover:shadow-pink-500'); calendarDates[i].classList.add('empty') } } // select only elements that are not empty const clickableDates = document.querySelectorAll('.clickable:not(.empty)'); clickableDates.forEach(dateElement => { dateElement.addEventListener('click', () => { const dateValue = dateElement.textContent.trim(); const year = 2017; const month = 1; // 1. 处理状态流转:新点击→当前选中,当前选中→历史,历史→清除所有样式 if (latestClicked !== null && latestClicked !== dateElement) { // 清除更早的历史元素所有额外类 if (historyClicked !== null) { historyClicked.classList.remove('bg-pink-500', 'shadow-md', 'shadow-pink-500'); } // 将当前选中元素转为历史状态(仅保留阴影) historyClicked = latestClicked; historyClicked.classList.remove('bg-pink-500'); } // 2. 给新点击元素添加完整选中样式 dateElement.classList.add('bg-pink-500', 'shadow-md', 'shadow-pink-500'); latestClicked = dateElement; const selectedDate = new Date(year, month, parseInt(dateValue)); const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; const dayOfWeek = daysOfWeek[selectedDate.getDay()]; selectedDateDayElement.textContent = dayOfWeek; selectedDateElement.textContent = dateValue; dateDisplay.style.display = 'block'; }); }); // Close the date details when clicked outside document.addEventListener('click', event => { if (!event.target.classList.contains('clickable')) { // 重置所有状态 if (latestClicked) { latestClicked.classList.remove('bg-pink-500', 'shadow-md', 'shadow-pink-500'); latestClicked = null; } if (historyClicked) { historyClicked.classList.remove('shadow-md', 'shadow-pink-500'); historyClicked = null; } dateDisplay.style.display = 'none'; } });
关键改动说明
- 用
historyClicked变量仅跟踪上一个点击的元素,确保最多只保留一个历史阴影状态 - 每次点击新日期时,自动清理更早的历史元素样式,完成状态层级流转
- 点击外部区域时,同步清除所有元素的额外类,重置整个状态
内容的提问来源于stack exchange,提问作者MiRAY
相关产品推荐
相关产品推荐

