VanillaCalendar点击日期/切换月份时事件标记消失的解决问询
问题:VanillaCalendar切换日期/月份后事件标记消失
我用VanillaCalendar展示指定日期的事件,实现逻辑是循环JSON数据,给有事件的日期节点添加事件标记的div元素。目前遇到的问题:点击日期或切换月份时,日期上的事件标记会消失,无法查看对应日期的事件。仅通过clickArrow事件加定时器重新调用事件分配函数解决了切换月份的问题,但点击日期时没有效果。
解决思路
VanillaCalendar在切换日期或月份时会重新渲染DOM,之前手动添加的事件标记会被清除。核心解决方式是在每次日历DOM渲染完成后自动重新挂载事件标记,而非依赖定时器或单一事件:
- 利用VanillaCalendar的
init和update生命周期钩子,分别在日历初始化和更新(切换日期/月份)后触发事件分配逻辑 - 优化事件分配函数,每次执行前清除已有的事件标记,避免重复添加
具体修改步骤
1. 调整日历配置,添加生命周期钩子
在日历配置的actions中添加init和update事件,替代原有的定时器逻辑:
var options = { // ... 原有配置不变 actions: { init: assignEventsToCalendar, // 初始化完成后执行 update: assignEventsToCalendar // 切换日期/月份后执行 } };
2. 优化事件分配函数,避免重复渲染
修改assignEventsToCalendar函数,先清除已存在的事件标记,再重新添加:
const assignEventsToCalendar = function() { // 先清除所有已存在的事件标记,防止重复添加 document.querySelectorAll('.event-wrapper').forEach(el => el.remove()); let eventData = data; for (const { month, days } of eventData) { for (const { day, events } of days) { const key = day.split('-').map(p => p.padStart(2, '0')).join('-'); let dayElement = document.querySelector(`[data-calendar-day="${key}"]`); if (dayElement) { let eventWrapper = document.createElement("div"); eventWrapper.classList.add("event-wrapper"); dayElement.append(eventWrapper); for (const { title, category } of events) { let singleEvent = document.createElement("div"); // 修正:category是数组,用展开语法添加类名 singleEvent.classList.add("event", ...category); eventWrapper.append(singleEvent); } } } } };
3. 移除冗余代码
因为init钩子会自动执行事件分配,所以删除calendar.init()之后的手动调用assignEventsToCalendar();
完整代码
HTML
<div id="calendar"></div> <!-- Vanilla Calendar --> <script src="https://cdn.jsdelivr.net/npm/@uvarov.frontend/vanilla-calendar/build/vanilla-calendar.min.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@uvarov.frontend/vanilla-calendar/build/vanilla-calendar.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@uvarov.frontend/vanilla-calendar/build/themes/light.min.css">
CSS
#calendar { max-width: 350px; } .vanilla-calendar-day__btn { position: relative; /* 确保事件标记的绝对定位相对于日期按钮 */ } .event-wrapper { position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: auto; } .event { display: inline-block; margin-right: 2px; width: 5px; height: 5px; } .event.Category1 { background-color: red; } .event.Category2 { background-color: blue; }
JavaScript
let data = [ {"month":"2024-2","days":[{"day":"2024-2-15","events":[{"title":"Event One","category":["Category1"]}]},{"day":"2024-2-21","events":[{"title":"Event Two","category":["Category2"]},{"title":"Event Three","category":["Category1"]}]},{"day":"2024-2-20","events":[{"title":"Event Four","category":["Category2"]}]}]}, {"month":"2024-3","days":[{"day":"2024-3-2","events":[{"title":"Event Five","category":["Category1"]}]},{"day":"2024-3-23","events":[{"title":"Event Six","category":["Category2"]}]}]} ]; document.addEventListener("DOMContentLoaded", function() { var currentDate = new Date().toISOString().slice(0, 10); var options = { date: { min: "1920-01-01", max: "2038-12-31" }, settings: { range: { min: currentDate }, visibility: { disabled: true, theme: 'light' } }, actions: { init: assignEventsToCalendar, update: assignEventsToCalendar } }; var calendar = new VanillaCalendar("#calendar", options); calendar.init(); }); const assignEventsToCalendar = function() { document.querySelectorAll('.event-wrapper').forEach(el => el.remove()); let eventData = data; for (const { month, days } of eventData) { for (const { day, events } of days) { const key = day.split('-').map(p => p.padStart(2, '0')).join('-'); let dayElement = document.querySelector(`[data-calendar-day="${key}"]`); if (dayElement) { let eventWrapper = document.createElement("div"); eventWrapper.classList.add("event-wrapper"); dayElement.append(eventWrapper); for (const { title, category } of events) { let singleEvent = document.createElement("div"); singleEvent.classList.add("event", ...category); eventWrapper.append(singleEvent); } } } } };
内容的提问来源于stack exchange,提问作者cece.dev
相关产品推荐
相关产品推荐

