我有一个向下拉菜单添加元素的循环。元素被添加,并且我想添加一个事件,该事件在用户单击元素之一时发生。所以我要添加一个这样的事件监听器。
for (var i = 0; cities.length > i; i++) {
if (cities[i].toLowerCase().indexOf(value.toLowerCase()) !== -1 && citiesList <= 10) {
citiesList ++;
dropdown.classList.add('show');
dropdown.innerHTML += '<a class="dropdown-item" id="dropdown_item-' + i + '" href="#">' + cities[i] + '</a>';
var item = document.getElementById('dropdown_item-' + i);
item.addEventListener("click", function(){ console.log("test") });
console.log(item);
}
}
但是当我单击元素时,即使console.log正确记录了该项目,该事件也不会触发,并且当我通过控制台手动添加侦听器时,它会起作用。我尝试使用超时功能,但没有成功。
当您将+=
与容器的innerHTML
一起使用时,仅从容器的HTML标记中就可以完全重新解析容器的内容。其他所有内容(例如不在HTML标记中的事件侦听器)都将丢失。使用insertAdjacentHTML
代替:
Element接口的insertAdjacentHTML()方法将指定的文本解析为HTML或XML,并将结果节点插入到DOM树中的指定位置。它不会重新解析正在使用该元素的元素,因此不会破坏该元素内部的现有元素。这避免了额外的序列化步骤,使其比直接的innerHTML操作要快得多。
insertAdjacentHTML
就是说,您似乎只是给该元素提供了一个ID,以便您可以选择它,然后在其上附加一个侦听器。动态ID是一个非常糟糕的主意-如果使用ID作为原因,则最好使用dropdown.insertAdjacentHTML('beforeend', '<a class="dropdown-item" id="dropdown_item-' + i + '" href="#">' + cities[i] + '</a>');
创建元素:
createElement
请记住,在给定当前代码的情况下,循环结束后const a = document.createElement('a');
a.className = "dropdown-item";
a.textContent = cities[i];
a.addEventListener("click", function() {
console.log("test")
});
dropdown.appendChild(a);
将等于i
。如果您在侦听器回调中引用cities.length
,则希望它引用用于特定迭代的i
,则需要一个块作用域范围内的i
:change
i
to
for (var i = 0; cities.length > i; i++) {
(或更妙的是,使用for (let i = 0; cities.length > i; i++) {
或类似的方法,而不是手动弄乱索引)