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

如何使用Vanilla JavaScript实现日历按天添加并展示事件

解决方案

你的核心问题是没有建立事件与具体日期的关联,而且在循环里重复绑定submit事件会导致多次触发。下面是优化方案,核心思路是用一个数据结构存储日期和对应事件的映射,给每个日历日期绑定明确的日期标识,点击时加载对应日期的事件。

关键优化点

  • 用dateEvents对象存储每个日期的事件列表,键为日期字符串(比如2024-05-15),值为事件数组
  • 给每个日历日期元素通过dataset.date绑定唯一的日期标识,替代随机ID
  • 只绑定一次submit事件,避免重复绑定;提交时根据当前选中的日期存储事件
  • 点击日期时,渲染该日期的已有事件到列表容器

修改后的完整代码

// 全局存储日期与事件的映射,初始为空
const dateEvents = {};
// 当前选中的日期
let selectedDate = null;

// 假设你已经获取了这些DOM元素
const dateContainer = document.getElementById('date-container');
const newEvent = document.getElementById('new-event');
const eventList = document.getElementById('event-list');
const taskInput = document.getElementById('task');

// 生成日历的循环(注意这里用let i避免闭包问题)
for (let i = 1; i <= days; i++) {
    // 生成完整日期字符串,需要你传入当前的year和month,比如2024-05-01
    const fullDate = `${year}-${String(month).padStart(2, '0')}-${String(i).padStart(2, '0')}`;
    
    let calendarDay = document.createElement('div');
    calendarDay.className = 'calendar-day';
    calendarDay.dataset.date = fullDate; // 绑定日期标识
    calendarDay.innerHTML = i;
    dateContainer.appendChild(calendarDay);

    // 日期点击事件
    calendarDay.addEventListener('click', () => {
        selectedDate = fullDate;
        newEvent.style.display = 'block';
        // 渲染当前日期的已有事件
        renderEventsForDate(selectedDate);
    });
}

// 只绑定一次submit事件,放在循环外面
eventList.addEventListener('submit', (e) => {
    e.preventDefault();
    if (!selectedDate || !taskInput.value.trim()) return;

    // 如果该日期还没有事件数组,初始化一个
    if (!dateEvents[selectedDate]) {
        dateEvents[selectedDate] = [];
    }
    // 添加新事件
    dateEvents[selectedDate].push(taskInput.value.trim());
    // 清空输入框并重新渲染事件列表
    taskInput.value = '';
    renderEventsForDate(selectedDate);
});

// 渲染指定日期的事件列表
function renderEventsForDate(date) {
    // 先清空现有列表
    const eventListContainer = newEvent.querySelector('.event-items') || createEventListContainer();
    eventListContainer.innerHTML = '';

    // 如果有事件,逐个创建li元素
    if (dateEvents[date]) {
        dateEvents[date].forEach(task => {
            let li = document.createElement('li');
            li.className = 'task-list';
            li.textContent = task;
            eventListContainer.appendChild(li);
        });
    }
}

// 创建事件列表容器(如果还不存在)
function createEventListContainer() {
    const container = document.createElement('div');
    container.className = 'event-items';
    newEvent.appendChild(container);
    return container;
}

代码说明

  1. 日期标识:用YYYY-MM-DD格式的字符串作为每个日期的唯一标识,比随机ID更直观且可追溯
  2. 事件存储:dateEvents对象让你可以轻松查找任意日期的事件,也方便后续持久化(比如存到localStorage)
  3. 避免重复绑定:submit事件只绑定一次,不会因为多次点击日期而重复触发
  4. 独立事件列表:renderEventsForDate函数负责渲染指定日期的事件,每次点击日期都会更新列表内容,确保只显示当前日期的事件

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:25:47