Next 和 Prev 按钮不适用于多个日历

Next and Prev buttons not working with multiple calendars

我在单个页面上呈现了多个日历,我需要使用下一个/上一个按钮(以及日期 select)才能查看不同的日期范围。我已经连接了外部的下一个/上一个按钮,但是,它们只影响页面上的最后一个日历。

我制作日历元素的 JS:

document.addEventListener('DOMContentLoaded', function() {
    for (let index = 1; index <= array_length; index++) {
        calendar_str = 'calendar_' + String(index);
        eval('var ' + calendar_str + ' = document.getElementById(\'' + calendar_str + '\');');
        var calendar = new FullCalendar.Calendar(eval('calendar_' + String(index)), {

        ... code here to setup calendar ...

          });
          calendar.render();
          calendar.setOption('contentHeight', 200);

          document.getElementById('prev-btn-ext').addEventListener('click', function() {
            calendar.prev(); // call method
          });

          document.getElementById('next-btn-ext').addEventListener('click', function() {
            calendar.next(); // call method
          });

    }
});

我的问题是,在呈现页面时,我可以看到所有日历,并且可以在它们之间拖放事件,但是,当我单击下一个和上一个按钮时,只有最后一个日历发生变化。我需要所有日历根据单个下一个/上一个按钮同步更改。

如您所见,我的日历实例被命名为 'calendar_1'、'calendar_2' 等,但是下一个和上一个按钮的 EventListener 仅查看 "calendar" 变量。我想知道我的问题是否与此有关,也许我需要以某种方式为每个日历实例指定 calendar.next() 或 calendar.prev() 的参数?

这是范围问题。

var calendar = 会在每次循环 运行 时重新定义 calendar 变量。由于您已经使用 var 定义了它,因此它的作用域是整个函数体的全局范围,并且扩展到分配给函数内点击事件的所有回调内部。这意味着即使在循环的先前迭代中定义的回调在执行时也会使用 calendar 的最新定义。

而如果您改写 let calendar =,这会将变量的范围限制在直接封闭块(在本例中为循环),并且意味着回调使用在该迭代中定义的版本当它们 运行 时循环,您的代码将按预期工作。这是将 let 添加到 JavaScript 的原因之一。

演示:https://codepen.io/ADyson82/pen/OJMbjQz

这是一篇有用的参考文章:What's the difference between using "let" and "var"?


但总的来说,与其使用 eval(这可能是一个安全问题,以及创建难以阅读的代码)来生成唯一的变量名,仅存储数组中的所有日历引用。所以这是另一种方法:

document.addEventListener("DOMContentLoaded", function () {
  let calendars = []; //calendars array
  //auto-detect the number of calendars on the page
  var calendarElements = document.querySelectorAll(".cal");

  calendarElements.forEach(function (cal) {
    let calendar = new FullCalendar.Calendar(cal, { plugins: ["dayGrid"] });
    calendar.render();
    calendar.setOption("contentHeight", 200);
    calendars.push(calendar); //add to array of calendars
  });

  document
    .getElementById("prev-btn-ext")
    .addEventListener("click", function () {
      calendars.forEach(function (cal) {
        cal.prev();
      });
    });

  document
    .getElementById("next-btn-ext")
    .addEventListener("click", function () {
      calendars.forEach(function (cal) {
        cal.next();
      });
    });
});

HTML 只需要一个小改动,将 "cal" class 添加到日历元素中,例如:

<button type="button" id="prev-btn-ext">Prev</button>
<button type="button" id="next-btn-ext">Next</button>
<div id='calendar_1' class="cal"></div>
<div id='calendar_2' class="cal"></div>
<div id='calendar_3' class="cal"></div>

演示:https://codepen.io/ADyson82/pen/zYrodyG