addEventListener 被忽略

addEventListener getting ignored

我有一个向下拉列表添加元素的循环。 添加了元素,我想添加一个在用户单击其中一个元素时发生的事件。 所以我添加了一个这样的事件监听器。

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 代替:

The insertAdjacentHTML() method of the Element interface parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position. It does not reparse the element it is being used on, and thus it does not corrupt the existing elements inside that element. This avoids the extra step of serialization, making it much faster than direct innerHTML manipulation.

dropdown.insertAdjacentHTML('beforeend', '<a class="dropdown-item" id="dropdown_item-' + i + '" href="#">' + cities[i] + '</a>');

也就是说,看起来您可能正在为元素提供一个 ID,以便您可以 select 它并随后将一个侦听器附加到它。动态 ID 是一个非常糟糕的主意 - 如果 ID 的原因,最好使用 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,则需要一个块范围的 i:change

for (var i = 0; cities.length > i; i++) {

for (let i = 0; cities.length > i; i++) {

(或者,更好的是,使用 Array.prototype.forEach 或类似的东西而不是手动弄乱索引)