Я построил простую демонстрацию (https://codepen.io/anon/pen/VgKQoq) элементов и объектов, создаваемых при нажатии кнопки: он создает элемент, а объект этого элемента затем помещается в массив «объектов». При нажатии кнопки удаления элемент и объект успешно удаляются с использованием идентификаторов.
Однако проблема заключается в том, что каждый раз, когда элемент удаляется, функция удаления иногда запускается слишком много раз в зависимости от того, какой элемент был нажат, и я не знаю, почему. В демоверсии откройте консоль javascript, создайте, например, 4 элемента, а затем удалите 3-й элемент, нажав «Удалить», и вы увидите, что произойдет.
кто-нибудь знает, почему это произошло? Я подумал, что это может быть связано с тем, что прослушиватель событий снова и снова добавляется к одним и тем же элементам несколько раз, но, похоже, он не работает при удалении. Любые объяснения и лучшие практики будут оценены здесь, спасибо.
var id = 0, objects = [], removes;
function createEntry() {
id++;
// create new element, append to #container & create new object
var container = document.querySelector('#container'),
newEntry = document.createElement("div"),
title = 'title text here',
description = 'description text here',
remove = 'remove',
dataId = id,
obj = new Entry(title, description, remove);
newEntry.classList.add("entry");
newEntry.innerHTML = '<span class = "title">' + title + '</span><span class = "description">' + description + '</span><span class = "remove">' + remove + '</span>';
container.appendChild(newEntry);
newEntry.setAttribute('data-id', id);
updateElements();
// constructor & push into array
function Entry(title, description, remove) {
this.title = title;
this.description = description;
this.remove = remove;
this.id = id;
objects.push(this);
}
// tests
console.info('JSON.stringify(obj): ' + JSON.stringify(obj));
console.info('obj.id: ' + obj.id);
function updateElements() {
removes = document.querySelectorAll(".remove");
listenForRemoves();
function listenForRemoves() {
for (let remove of removes) {
remove.removeEventListener("click", removeElements);
remove.addEventListener("click", removeElements);
}
}
function removeElements() {
let removedId = this.parentNode.getAttribute('data-id'),
objToRemove = objects.find(obj => obj.id == removedId); // not used
this.parentNode.remove(); console.info('removed id ' + removedId);
console.info('objects before: '); for (let object of objects) { console.info(JSON.stringify(object))};
objects = objects.filter(obj => obj.id != removedId); // doesn't use objToRemove
console.info('objects now: '); for (let object of objects) { console.info(JSON.stringify(object))};
}
}
// works but why the repeating console logs twice?
}button { display: block }
.entry {
width: 100%;
display: block;
padding: 10px;
border: 1px solid #f5f5f5;
}
span {
display: block;
width: 100%;
}
section { background: lightgreen }<button id='btn' onclick='createEntry()'>Create</button>
<section id='container'></section>Обновлено: Есть еще идеи? Я добавил remove.removeEventListener("click", removeElements);, который теперь избавляется от множества дубликатов, но консоль по-прежнему регистрируется только дважды (ну... иногда!?). Новая ссылка codepen обновлена выше
Вы добавляете новый прослушиватель событий к одному и тому же элементу каждый раз, когда что-то обновляется, не удаляя предыдущие прослушиватели событий.
Я добавил 'remove.removeEventListener("click", removeElements)', который удалил много повторяющихся журналов консоли, но теперь консоль регистрируется дважды. У кого-нибудь есть идеи? У меня закончились идеи, и я пробовал много изменений



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я точно не знаю, что происходит, но у вас есть все эти функции, вложенные в функцию createEntry. Попробуйте переместить их за пределы этой функции. Кажется, это решает проблему в моих тестах:
var id = 0, objects = [], removes;
function createEntry() {
id++;
// create new element, append to #container & create new object
var container = document.querySelector('#container'),
newEntry = document.createElement("div"),
title = 'title text here',
description = 'description text here',
remove = 'remove',
dataId = id,
obj = new Entry(title, description, remove);
newEntry.classList.add("entry");
newEntry.innerHTML = '<span class = "title">' + title + '</span><span class = "description">' + description + '</span><span class = "remove">' + remove + '</span>';
container.appendChild(newEntry);
newEntry.setAttribute('data-id', id);
updateElements();
// constructor & push into array
function Entry(title, description, remove) {
this.title = title;
this.description = description;
this.remove = remove;
this.id = id;
objects.push(this);
}
// tests
console.info('JSON.stringify(obj): ' + JSON.stringify(obj));
console.info('obj.id: ' + obj.id);
}
function updateElements() {
removes = document.querySelectorAll(".remove");
listenForRemoves();
function listenForRemoves() {
for (let remove of removes) {
remove.removeEventListener("click", removeElements);
remove.addEventListener("click", removeElements);
}
}
}
function removeElements(e) {
let removedId = this.parentNode.getAttribute('data-id'),
objToRemove = objects.find(obj => obj.id == removedId); // not used
this.parentNode.remove(); console.info('removed id ' + removedId);
console.info('objects before: '); for (let object of objects) { console.info(JSON.stringify(object) + " " + e.target)};
objects = objects.filter(obj => obj.id != removedId); // doesn't use objToRemove
console.info('objects now: '); for (let object of objects) { console.info(JSON.stringify(object))};
}
спасибо - не уверен, как вложенные функции вызвали эту ошибку, но по вашему совету я также снова отредактировал оригинал, и это сработало, удалив вложенные функции
потому что вы связываете слишком много событий в цикле, даже если это не нужно