无法删除事件侦听器 Javascript

Unable to remove event listener Javascript

我试图在添加新事件处理程序之前删除事件处理程序。否则它会触发多次。这是调用 attach/remove 它的方法。

function attachRemoveBookEvent(bookEl) {

    function remove() {
        bookEl.remove();

        for(let i=0; i < bookObjects.length; i++) {
            if(bookObjects[i].id == bookEl.getAttribute("data-id")) {
                bookObjects.splice(i, 1);
                break;
            }
        }

        hideContainer(removeContainer);
    }
    removeConfirm.removeEventListener("click", remove);
    removeConfirm.addEventListener("click", remove);
}

我不确定是否因为方法实际上不相同,当我按下按钮时它会多次触发。

解释器每次遇到 function 关键字时,都会创建一个新函数。所以,如果你调用 attachRemoveBookEvent 并附加一个监听器,然后你再次调用 attachRemoveBookEvent,你将不再有对 original remove 的引用在原始调用中创建的函数 - 相反,您有一个对刚刚创建的 new remove 函数的引用。不知何故,您必须确保传入的函数与调用 addEventListener 的函数相同。一种可能性是对附加到 removeConfirm:

的当前 remove 进行持久引用
let remove = null;
function attachRemoveBookEvent(bookEl) {
  removeConfirm.removeEventListener("click", remove);
  remove = function remove() {
    bookEl.remove();
    for(let i=0; i < bookObjects.length; i++) {
      if(bookObjects[i].id == bookEl.getAttribute("data-id")) {
        bookObjects.splice(i, 1);
        break;
      }
    }
    hideContainer(removeContainer);
  }
  removeConfirm.addEventListener("click", remove);
}

或者,根据您想要的逻辑类型,您可以永久保持事件侦听器,而不是重新附加它,只重新分配 bookEl,在持久化外部变量中,有点像:

let currentBookEl = null;
function remove() {
  if (currentBookEl) currentBookEl.remove();
  for(let i=0; i < bookObjects.length; i++) {
    if(bookObjects[i].id == bookEl.getAttribute("data-id")) {
      bookObjects.splice(i, 1);
      break;
    }
  }
  hideContainer(removeContainer);
}
function attachRemoveBookEvent(bookEl) {
  currentBookEl = bookEl;
}

此外,当您试图在数组中查找元素的索引时,比手动迭代 bookObjectsbreaking 更好的选择是 findIndex

const idToFind = bookEl.getAttribute("data-id");
const index = bookObjects.find(({ id }) => id === idToFind);
bookObjects.splice(i, 1);

您可以向元素添加 class,并且仅在 class 不存在时才添加侦听器

function attachRemoveBookEvent(bookEl) {

  function remove() {
    bookEl.remove();

    for (let i = 0; i < bookObjects.length; i++) {
      if (bookObjects[i].id == bookEl.getAttribute("data-id")) {
        bookObjects.splice(i, 1);
        break;
      }
    }

    hideContainer(removeContainer);
  }

  if(!removeConfirm.classList.contains('someClass')) {
    removeConfirm.classList.add('someClass')
    removeConfirm.addEventListener("click", remove);
  }


}