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>
我在单个页面上呈现了多个日历,我需要使用下一个/上一个按钮(以及日期 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>