You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现日历仅为最新上一个点击元素添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:30:04