我正在处理可能会更改数量的图像列表,因此固定ID和事件侦听器不实用。下面的代码生成具有正确ID的正确数量的按钮,但只有最后一个具有功能事件监听器。
for (var i = 0; i < amount; i++) {
!function(index) {
if (items[index].classList.contains('current')) {
document.getElementById('selectButtons').innerHTML += '<button id=\"bitems' + index + '\"> ⬤ <span class=\"offscreen\">Item ' + i + '</span></button>';
}
else
{
document.getElementById('selectButtons').innerHTML += '<button id=\"bitems' + index + '\"> ◯ <span class=\"offscreen\">Item ' + i + '</span></button>';
}
document.getElementById('bitems' + index).addEventListener("click", function(ev) {
alert("clicked");
});
}(i);
}
显然,IIFE并没有按照预期存储个别变量,但我无法弄清楚原因。毕竟,这就是循环中IIFE的全部目的。
非常感谢任何帮助。
答案 0 :(得分:2)
IIFE工作正常。实际上,每次更新selectButtons的innerHTML时,都会重新创建DOM,并且附加到它的所有事件都会消失!
您可以将按钮添加到其中,而不是在每次迭代中更新innerHTML,而不是:
for (var i = 0; i < 10; i++) {
!function(index) {
var button = document.createElement("BUTTON");
var t = document.createTextNode("Button" + index);
button.appendChild(t);
document.getElementById('selectButtons').appendChild(button);
button.addEventListener("click", function(ev) {
alert("clicked +" +index);
});
}(i);
}
请添加您需要的条件。
答案 1 :(得分:1)
每次执行innerHTML +=
时,您将替换整个HTML,从而删除以前安装的所有事件处理程序。这是一个很好的理由,不将HTML视为您innerHTML
到页面上的一串字符串。而不是字符串,从元素的角度思考,如在另一个答案中。那么你也不需要将ID用作穷人的变量名&#34;参考元素;你可以使用元素本身。
你不需要笨拙的IIFE。这是let
的用途。
以下是您的代码的清理版本:
var buttons = document.getElementById('selectButtons');
for (let i = 0; i < amount; i++) {
var current = items[i].classList.contains('current');
var button = document.createElement("BUTTON");
var bullet = document.createTextNode(current ? '◯' : '⬤')
var span = document.createElement('span');
van spanText = `Item ${i}`;
span.className = 'offscreen';
span.appendChild(spanText);
button.appendChild(bullet);
button.appendChild(span);
buttons.appendChild(button);
button.addEventListener('click', () => alert(`clicked ${i}`));
}
如果你想保存一两行,你可以利用appendChild
返回附加子项和链的事实:
buttons.appendChild(button).appendChild(span).appendChild(spanText);
如果您要做很多事情,最好创建一些微小的实用程序:
function createElementWithText(tag, text) {
var b = document.createElement(tag);
var t = document.createTextNode(text);
b.appendChild(t);
return b;
}
function button(text) { return createElementWithText('button', text); }
function span(text) { return createElementWithText('span', text); }
现在,您可以更简洁地编写代码:
var buttons = document.getElementById('selectButtons');
for (let i = 0; i < amount; i++) {
var current = items[i].classList.contains('current');
var button = button(current ? '◯' : '⬤');
var span = span(`Item ${i}`);
span.className = 'offscreen';
buttons.appendChild(button).appendChild(span);
button.addEventListener('click', () => alert(`clicked ${i}`));
}
实际上,创建一个文档片段,提前添加所有按钮,然后将其一次插入DOM中,会更为合适。
然而,在实践中,你最好使用某种模板语言,你可以写下这样的语言:
<div id="selectButtons">
{{for i upto amount}}
<button {{listen 'click' clicked}}>
{{if items[i] hasClass 'current'}}◯{{else}}⬤{{endIf}}
<span class="offscreen">Index {{i}}</span>
</button>
{{endFor}}
</div>
推荐特定的模板语言超出了本答案的范围。有很多很好的,比如Mustache,谷歌可以帮助你找到,通过搜索,例如&#34; javascript模板语言&#34;。