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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:24:54