如何使用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; }
代码说明
- 日期标识:用
YYYY-MM-DD格式的字符串作为每个日期的唯一标识,比随机ID更直观且可追溯 - 事件存储:
dateEvents对象让你可以轻松查找任意日期的事件,也方便后续持久化(比如存到localStorage) - 避免重复绑定:submit事件只绑定一次,不会因为多次点击日期而重复触发
- 独立事件列表:
renderEventsForDate函数负责渲染指定日期的事件,每次点击日期都会更新列表内容,确保只显示当前日期的事件
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

