如何检查动态创建的按钮被单独和总共单击的频率?
How to check, how often have dynamically created buttons been clicked, individually and in total?
我创建了一个带有按钮的循环。我还创建了一个 eventListener,它为每个按钮保留一个计数。我希望当所有按钮都被按下至少 3 次时发生一些事情,所以我创建了一个 if 语句来检查计数是否为 3 并将 1 加到另一个计数,但即使按下了多个按钮,另一个计数仍保持为 1 3次。
for (let i = 0; i < 7; i++) {
let btn = document.createElement('button');
btn.classList.add('buttons');
btn.id = 'button' + i;
document.getElementById('box').appendChild(btn);
let count = 0;
let count2 = 0;
btn.addEventListener('click', () => {
count++;
console.log(count);
if (count === 3) {
console.log('3');
count2++;
console.log(count2);
} else {
console.log('not 3');
}
});
}
#box button { min-width: 20px; min-height: 20px; }
.as-console-wrapper { max-height: 87%!important; }
body { margin: 0; }
<div class="box" id="box">
</div>
所以 count 变量工作正常,当 1 个按钮被点击 3 次时,count2 变量变为 1,但它保持在 1,我似乎无法找出原因。最后 count2 应该是 7,因为有 7 个按钮。
正如 Vladimir 在评论中暗示的那样,这是一个范围界定问题。
变量计数仅在事件侦听器内部声明,因此稍后当您按下不同的按钮时,您的代码会对不同的计数变量执行 count++
。
要解决此问题,请声明 var count
而不是 let count
- 这将使它成为全局的。
或者在for
循环之前声明计数变量。
顺便说一句:确保在 count
达到 3 时停止更新,因为它不会更新 count2
如果它达到 4 或更高
除了已经指出 OP 问题的所有评论之外,我建议基于 storing/updating 个 button-counts Map
-实例中的不同方法。
通过在顶部引入 event-delegation,可以摆脱多个即时(对于每个动态创建的按钮)应用的事件处理程序,这会强制方法处理不同的计数器范围(处理程序范围和 for
块作用域).
只有一个处理程序订阅了一个 parent-node 的 'click'
事件。此处理程序通过查找单个按钮 click-count.
来跟踪和处理各种 click-count 状态
function createButton(id) {
let elmNode = document.createElement('button');
elmNode.classList.add('buttons');
elmNode.id = `button${ id }`;
return elmNode;
}
function main() {
// keeps track of and handles the various click count states.
function handleButtonClick({ target }) {
const btnNode = target.closest('button');
// update a single buttons click count total.
const buttonClickTotal = clickCountStorage.get(btnNode) + 1;
clickCountStorage.set(btnNode, buttonClickTotal);
const clickCountList = Array
.from(
clickCountStorage.values()
);
// calculate click count total of all buttons.
const allButtonsClickTotal = clickCountList
.reduce((total, count) => total + count, 0);
// check whether the OP's each button minimum 3 times click applies.
const isEveryButtonHasBeenClickedAtLeastThreeTimes = clickCountList
.every(count => count >= 3);
console.log({
buttonClickTotal,
allButtonsClickTotal,
isEveryButtonHasBeenClickedAtLeastThreeTimes,
});
}
const clickCountStorage = new Map;
const root = document.querySelector('#box');
// make use of event delegation ...
// - a single eventhandler subscribed once to
// a single parent node's 'click' event.
root.addEventListener('click', handleButtonClick)
for (let elmNode, i = 0; i < 7; i++) {
elmNode = createButton(i);
// establish a new button reference related click count.
clickCountStorage.set(elmNode, 0);
root.appendChild(elmNode);
}
}
main();
#box button { min-width: 20px; min-height: 20px; }
.as-console-wrapper { max-height: 87%!important; }
body { margin: 0; }
<div class="box" id="box">
</div>
我创建了一个带有按钮的循环。我还创建了一个 eventListener,它为每个按钮保留一个计数。我希望当所有按钮都被按下至少 3 次时发生一些事情,所以我创建了一个 if 语句来检查计数是否为 3 并将 1 加到另一个计数,但即使按下了多个按钮,另一个计数仍保持为 1 3次。
for (let i = 0; i < 7; i++) {
let btn = document.createElement('button');
btn.classList.add('buttons');
btn.id = 'button' + i;
document.getElementById('box').appendChild(btn);
let count = 0;
let count2 = 0;
btn.addEventListener('click', () => {
count++;
console.log(count);
if (count === 3) {
console.log('3');
count2++;
console.log(count2);
} else {
console.log('not 3');
}
});
}
#box button { min-width: 20px; min-height: 20px; }
.as-console-wrapper { max-height: 87%!important; }
body { margin: 0; }
<div class="box" id="box">
</div>
所以 count 变量工作正常,当 1 个按钮被点击 3 次时,count2 变量变为 1,但它保持在 1,我似乎无法找出原因。最后 count2 应该是 7,因为有 7 个按钮。
正如 Vladimir 在评论中暗示的那样,这是一个范围界定问题。
变量计数仅在事件侦听器内部声明,因此稍后当您按下不同的按钮时,您的代码会对不同的计数变量执行 count++
。
要解决此问题,请声明 var count
而不是 let count
- 这将使它成为全局的。
或者在for
循环之前声明计数变量。
顺便说一句:确保在 count
达到 3 时停止更新,因为它不会更新 count2
如果它达到 4 或更高
除了已经指出 OP 问题的所有评论之外,我建议基于 storing/updating 个 button-counts Map
-实例中的不同方法。
通过在顶部引入 event-delegation,可以摆脱多个即时(对于每个动态创建的按钮)应用的事件处理程序,这会强制方法处理不同的计数器范围(处理程序范围和 for
块作用域).
只有一个处理程序订阅了一个 parent-node 的 'click'
事件。此处理程序通过查找单个按钮 click-count.
function createButton(id) {
let elmNode = document.createElement('button');
elmNode.classList.add('buttons');
elmNode.id = `button${ id }`;
return elmNode;
}
function main() {
// keeps track of and handles the various click count states.
function handleButtonClick({ target }) {
const btnNode = target.closest('button');
// update a single buttons click count total.
const buttonClickTotal = clickCountStorage.get(btnNode) + 1;
clickCountStorage.set(btnNode, buttonClickTotal);
const clickCountList = Array
.from(
clickCountStorage.values()
);
// calculate click count total of all buttons.
const allButtonsClickTotal = clickCountList
.reduce((total, count) => total + count, 0);
// check whether the OP's each button minimum 3 times click applies.
const isEveryButtonHasBeenClickedAtLeastThreeTimes = clickCountList
.every(count => count >= 3);
console.log({
buttonClickTotal,
allButtonsClickTotal,
isEveryButtonHasBeenClickedAtLeastThreeTimes,
});
}
const clickCountStorage = new Map;
const root = document.querySelector('#box');
// make use of event delegation ...
// - a single eventhandler subscribed once to
// a single parent node's 'click' event.
root.addEventListener('click', handleButtonClick)
for (let elmNode, i = 0; i < 7; i++) {
elmNode = createButton(i);
// establish a new button reference related click count.
clickCountStorage.set(elmNode, 0);
root.appendChild(elmNode);
}
}
main();
#box button { min-width: 20px; min-height: 20px; }
.as-console-wrapper { max-height: 87%!important; }
body { margin: 0; }
<div class="box" id="box">
</div>